简体   繁体   English

为什么'this.ContentTemplate.FindName'会在自己的模板上抛出InvalidOperationException?

[英]Why would 'this.ContentTemplate.FindName' throw an InvalidOperationException on its own template?

Ok... this has me stumped. 好的...这让我很难过。 I've overridden OnContentTemplateChanged in my UserControl. 我在UserControl中覆盖了OnContentTemplateChanged。 I'm checking that the value passed in for newContentTemplate does in fact equal this.ContentTemplate (it does) yet when I call this... 我正在检查传入newContentTemplate的值实际上是否等于this.ContentTemplate(它确实)当我调用它时...

var textBox = this.ContentTemplate.FindName("EditTextBox", this);

...it throws the following exception... ...它抛出以下异常......

"This operation is valid only on elements that have this template applied." “此操作仅对应用此模板的元素有效。”

Per a commenter in another related question, he said you're supposed to pass in the content presenter for the control, not the control itself, so I then tried this... 根据另一个相关问题的评论者,他说你应该传入内容主持人来控制,而不是控件本身,所以我试过这个......

var cp = FindVisualChild<ContentPresenter>(this);

var textBox = this.ContentTemplate.FindName("EditTextBox", cp);

where FindVisualChild is just a helper function used in MSDN's example (see below) to find the associated content presenter. 其中FindVisualChild只是MSDN示例中使用的辅助函数(见下文),用于查找关联的内容演示者。 While 'cp' is found, it too throws the same error. 找到“cp”时,它也会抛出同样的错误。 I'm stumped!! 我很难过!

Here's the helper function for reference... 这是帮助函数供参考......

private childItem FindVisualChild<childItem>(DependencyObject obj)
    where childItem : DependencyObject
{
    for(int i = 0 ; i < VisualTreeHelper.GetChildrenCount(obj) ; i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(obj, i);
        if(child != null && child is childItem)
            return (childItem)child;
        else
        {
            childItem childOfChild = FindVisualChild<childItem>(child);
            if(childOfChild != null)
                return childOfChild;
        }
    }
    return null;
}

M 中号

在调用FindName方法之前显式应用模板将防止此错误。

this.ApplyTemplate(); 

As John pointed out, the OnContentTemplateChanged is being fired before it is actually applied to the underlying ContentPresenter. 正如John指出的那样,OnContentTemplateChanged在实际应用于底层ContentPresenter之前就被触发了。 So you'd need to delay your call to FindName until it is applied. 因此,在应用FindName之前,您需要延迟对FindName的调用。 Something like: 就像是:

protected override void OnContentTemplateChanged(DataTemplate oldContentTemplate, DataTemplate newContentTemplate) {
    base.OnContentTemplateChanged(oldContentTemplate, newContentTemplate);

    this.Dispatcher.BeginInvoke((Action)(() => {
        var cp = FindVisualChild<ContentPresenter>(this);
        var textBox = this.ContentTemplate.FindName("EditTextBox", cp) as TextBox;
        textBox.Text = "Found in OnContentTemplateChanged";
    }), DispatcherPriority.DataBind);
}

Alternatively, you may be able to attach a handler to the LayoutUpdated event of the UserControl, but this may fire more often than you want. 或者,您可以将处理程序附加到UserControl的LayoutUpdated事件,但这可能会比您想要的更频繁地触发。 This would also handle the cases of implicit DataTemplates though. 这也可以处理隐式DataTemplates的情况。

Something like this: 像这样的东西:

public UserControl1() {
    InitializeComponent();
    this.LayoutUpdated += new EventHandler(UserControl1_LayoutUpdated);
}

void UserControl1_LayoutUpdated(object sender, EventArgs e) {
    var cp = FindVisualChild<ContentPresenter>(this);
    var textBox = this.ContentTemplate.FindName("EditTextBox", cp) as TextBox;
    textBox.Text = "Found in UserControl1_LayoutUpdated";
}

The ContentTemplate isn't applied to the ContentPresenter until after that event. 在该事件之后,ContentTemplate才会应用于ContentPresenter。 While the ContentTemplate property is set on the control at that point, it hasn't been pushed down to bindings internal to the ControlTemplate, like the ContentPresenter's ContentTemplate. 虽然此时在控件上设置了ContentTemplate属性,但尚未将其下推到ControlTemplate内部的绑定,如ContentPresenter的ContentTemplate。

What are you ultimately trying to do with the ContentTemplate? 你最终想用ContentTemplate做什么? There might be a better overall approach to reach your end goal. 可能有更好的整体方法来实现您的最终目标。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM