我在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.特别是放在类库中使用自定义控件时,留意是否完整的调用链路
- 应在Themes文件夹下
- 应在Themes文件夹下添加Generic.xaml资源字典
- 应在Generic.xaml中有对自定义控件的引用
- 应在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