首页 > 其他分享 >关于WPF自定义控件OnApplyTemplate不执行,手动调用Template.FindName返回空的问题

关于WPF自定义控件OnApplyTemplate不执行,手动调用Template.FindName返回空的问题

时间:2022-09-26 12:11:09浏览次数:80  
标签:控件 自定义 OnApplyTemplate Template Loaded textbox

我在wpf项目中手写了一个自定义控件,运行得相当的正常,后续调用时,反复遇到问题,前前后后折腾了好几次

代码

 public ExtendCombox()
        {
            Loaded += (e, s) =>
            {
                textbox.TextChanged += Textbox_TextChanged;
                textbox.PreviewKeyDown += Textbox_PreviewKeyDown;
                textbox.GotFocus += OnGotFocus;
                textbox.LostFocus += OnLostFocus;
                textbox.PreviewMouseDown += OnPreviewMouseDown;
                dataGrid.PreviewMouseLeftButtonUp += DataGrid_MouseLeftButtonDown;
                textbox.FontSize = FontSize;
                ClipBound();
            };
            Unloaded += (e, s) =>
            {
                textbox.TextChanged -= Textbox_TextChanged;
                textbox.PreviewKeyDown -= Textbox_PreviewKeyDown;
                textbox.GotFocus -= OnGotFocus;
                textbox.LostFocus -= OnLostFocus;
                textbox.PreviewMouseDown -= OnPreviewMouseDown;
                dataGrid.PreviewMouseLeftButtonUp -= DataGrid_MouseLeftButtonDown;
            };


        }


 public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            textbox = Template.FindName("textbox", this) as TextBox;

            toggleButton = Template.FindName("toggleButton", this) as ToggleButton;
            dataGrid = Template.FindName("dataGrid", this) as ListView;
            if (Delay > 0) {
                dispatcher = new DispatcherTimer();
                dispatcher.Tick += Dispatcher_Tick;
                dispatcher.Interval = new TimeSpan(0, 0, 0, 0, Delay);
            }
        }

问题及解决

问题1.当我把他迁移到控件库中时,再次使用自定义控件不再执行OnApplyTemplate,调用Template.FindName返回值也为空

产生原因是我在迁移到类库后有代码错误,引用了样式,在类库中获取不到,导致编译通过,执行时不报错,现象却是没有执行OnApplyTemplate,注意这句:Style="{StaticResource ToggleButtonIconTransparent}"

<ToggleButton Focusable="False" Grid.Column="1" x:Name="toggleButton" Style="{StaticResource ToggleButtonIconTransparent}" hc:IconSwitchElement.Geometry="{StaticResource UpGeometry}" hc:IconSwitchElement.GeometrySelected="{StaticResource DownGeometry}"/>

 问题2.我在TabControl中使用自定义控件,第一个TabItem中使用正常,第二,第三个不能执行OnApplyTemplate(),导致我在Loaded中获取不到控件

这个问题其实是Loaded和OnApplyTemplate的执行顺序导致的,由于TabCcntrol加载时会加载所有的TabItem,所以进入第一个界面时自定义控件中的Loaded都会执行,而OnApplyTemplate需要你切换TabItem时才会执行,也就导致Loaded在前,OnApplyTemplate在后,感觉是OnApplyTemplate没有执行,我的解决方法是手动触发一次OnApplyTemplate

 public ExtendCombox()
        {
            Loaded += (e, s) =>
            {
                if (textbox == null) {
                   if(!ApplyTemplate())
                        OnApplyTemplate();
                }

                textbox.TextChanged += Textbox_TextChanged;
                textbox.PreviewKeyDown += Textbox_PreviewKeyDown;
                textbox.GotFocus += OnGotFocus;
                textbox.LostFocus += OnLostFocus;
                textbox.PreviewMouseDown += OnPreviewMouseDown;
                dataGrid.PreviewMouseLeftButtonUp += DataGrid_MouseLeftButtonDown;
                textbox.FontSize = FontSize;
                ClipBound();
            };

留意if (!ApplyTemplate()) OnApplyTemplate();这句,如果没有加载 就加载一下

其他不执行OnApplyTemplate的原因

以下问题虽然我没有遇到,还是在这里记录一下

1.特别是放在类库中使用自定义控件时,留意是否完整的调用链路

  1. 应在Themes文件夹下
  2. 应在Themes文件夹下添加Generic.xaml资源字典
  3. 应在Generic.xaml中有对自定义控件的引用
  4. 应在App.xaml中完成对Genneric的引用

 

 

 

 

 

 

 

 

 

2.在自定义样式中设置样式键

static ExtendCombox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ExtendCombox), new FrameworkPropertyMetadata(typeof(ExtendCombox)));
        }

3.在运行程序,类库的Assembly.cs文件中应包含样式的默认获取方式

[assembly:ThemeInfo(
    ResourceDictionaryLocation.None, //主题特定资源词典所处位置
                             //(未在页面中找到资源时使用,
                             //或应用程序资源字典中找到时使用)
    ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
                                      //(未在页面中找到资源时使用,
                                      //、应用程序或任何主题专用资源字典中找到时使用)
)]

 

 相关链接:wpf - 在自定义控件中未调用应用程序模板 - 堆栈溢出 (stackoverflow.com)

标签:控件,自定义,OnApplyTemplate,Template,Loaded,textbox
From: https://www.cnblogs.com/xiaoke-/p/16730318.html

相关文章