GetTemplateChild在不同的项目中返回null

时间:2016-02-02 14:05:39

标签: c# wpf combobox

我创建了FilteredComboBox,它源自标准WPF comboBox。到目前为止,这个新的UserControl在设计它的原始测试应用程序中运行良好。 现在我已经将类复制到我的主应用程序中,当我尝试访问PART_EditableTextBox的{​​{1}}子项时,我得到 null引用异常

ComboBox

问题出现在我要添加 public override void OnApplyTemplate() { base.OnApplyTemplate(); EditableTextBox.SelectionChanged += EditableTextBox_SelectionChanged; ItemsPopup.Focusable = true; } private TextBox EditableTextBox { get { return (TextBox)GetTemplateChild("PART_EditableTextBox"); } } 事件的行中。在做一些研究时,总是建议等到SelectionChanged完成,这基本上是在ApplyTemplate

完成的

我检查了主应用程序中的基础模板,它应该包含base.OnApplyTemplate();

有关此处可能出现的问题或我可以采取哪些措施进行进一步调查的任何想法?

更新:我在查看了泽维尔的一些建议后发现了问题。 PART_EditableTextBox的问题是它仅在ComboBox定义为

时可用
PART_EditableTextBox

我不得不承认,在我提到的第二个项目中并非如此。如果ComboBox不可编辑,那么它根本就没有EditableTextBox: - /

感谢支持人员......

2 个答案:

答案 0 :(得分:0)

您应该验证您是否获得了预期的模板。如果您确定模板具有您想要的命名部分,但尝试检索它会返回null,当您尝试访问它时,它几乎肯定不会应用于控件。

您提到当您将控件从一个程序集移动到另一个程序集时问题就开始了。也许您将其移动到的装配不能正确设置。

例如,您是否希望模板作为默认主题的一部分自动应用?如果是这样,样式是否在程序集中的正确位置(在themes / generic.xaml中引用或引用),并且您是否在AssemblyInfo.cs文件中正确定义了ThemeInfo attribute? (另外,您是否覆盖用户控件中的元数据以使用正确的资源键?)

如果您正在某处明确地应用模板,那么基类的默认值可能会在您之前应用,因此您在应用默认值时会崩溃,并且永远不会到达应用您的默认值。

有几件事可能是错的,如果不检查一切,很难知道它是什么。希望我所说的话会给你一个关于这个问题的暗示。

注意:作为一种惯例,我总是在尝试检索模板部件后添加空检查。您永远无法确定如何使用控件,以及可能在不同场景中应用的模板。例如,使用该控件的任何人都可以覆盖该模板,而不是指定您期望的部件。在我看来,最好让控件不像设计那样运行而不是使应用程序崩溃。

注意2:每次要访问模板部件时,不应该有一个查找模板部件的属性,而应该在OnApplyTemplate中查找一次并将其存储为成员变量。每次从代码访问控件时都会保存模板查找。

答案 1 :(得分:0)

您是否考虑过将其设置为自定义控件与UserControl?我认为您遇到的问题可能是由于在对象生命周期中初始化UserControl的时间。

在下面的案例中,您在部件可以访问之前尝试连接事件处理程序。

解决这类问题的一种方法是使用Dispatcher等到安全地连接事件处理程序。

public override void OnApplyTemplate()
{
    base.OnApplyTemplate();
    GetTemplateParts();
    ItemsPopup.Focusable = true;
}

protected void GetTemplateParts()
{
        Dispatcher.CurrentDispatcher.BeginInvoke(
            DispatcherPriority.Loaded, 
            new Action(() => 
            { 
                EditableTextBox.SelectionChanged += EditableTextBox_SelectionChanged;
            }));
}