x:如果元素包含在UserControl的内容中(Silverlight),则名称不起作用

Kor*_*tak 4 silverlight user-controls code-behind wrapper

情况:

我有一个UserControl像这样的"包装器面板" (为简洁起见,删除了名称空间和视觉细节):

<UserControl ...>
<Grid x:Name="LayoutRoot" Background="White">
    <ContentPresenter x:Name="integratedPanelContent" Margin="5" /> 
</Grid>
</UserControl>
Run Code Online (Sandbox Code Playgroud)

然后在Code-behind中我注册了一个依赖属性

public FrameworkElement PanelContent
{
    get { return (FrameworkElement)GetValue(PanelContentProperty); }
    set { SetValue(PanelContentProperty, value); }
}
public static readonly DependencyProperty PanelContentProperty =
    DependencyProperty.Register("PanelContent", typeof(FrameworkElement), typeof(MyWrapperPanel),
      new PropertyMetadata(null, OnPanelContentChanged));

private static void OnPanelContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    ((MyWrapperPanel)d).OnSetContentChanged(e);
}

protected virtual void OnSetContentChanged(DependencyPropertyChangedEventArgs e)
{
    if (PanelContent != null)
        integratedPanelContent.Content = PanelContent;
}
Run Code Online (Sandbox Code Playgroud)

现在我可以将任何内容包装到我的控件中:

<my:MyWrapperPanel x:Name="myWrap">
    <my:MyWrapperPanel.PanelContent>
        <TextBlock x:Name="tbxNothing" Text="Nothing" />
    </my:MyWrapperPanel.PanelContent>
</my:MyWrapperPanel>
Run Code Online (Sandbox Code Playgroud)

问题描述:

每当我尝试在代码隐藏中使用引用tbxNothing时,系统抛出,NullReferenceException因为tbxNothing虽然作为引用存在,但并不指向XAML中定义的TextBlock,而是null.

可能(但不方便)的解决方法:

有一个解决方法,我x:Name从TextBlock中删除,然后我明确定义调用的私有TextBlock tbxNothing.然后在OnNavigatedTo事件处理程序中,我按以下方式分配值:

tbxNothing = myWrap.PanelContent as TextBlock;
Run Code Online (Sandbox Code Playgroud)

这可行,但不是正确的方法,因为如果内容是包含所需控件的堆栈面板,我必须遍历树以找到我需要的东西,这非常不方便.

题:

为什么在用户控件(描述的方式)中包装时文本块不再可见,以及如何通过其代码隐藏中的x:Name来获取它?

Ant*_*nes 5

问题是你的面板内容在两个凳子之间下降.一方面,名称为"tbxNothing"的内容是在主页面的名称范围内创建的.但是,此时它未添加到对象树中.另一方面,作为UserControl的MyWrapperPanel具有自己的名称范围,并且在其下面的对象树中添加了具有名称"tbxNothing"的项目. FindName在主页面上找不到MyWrapperPanel中的任何内容,因为它有自己的名称范围,并且FindName在MyWrapperPanel上找不到"tbxNothing",因为它在名称范围内不存在(实际上是在主页面中创建的).

答案是不要以a UserControl为基础MyWrapperPanel.而是创建一个Silverlight模板控件.修改它继承的基类ContentControl并调整其默认模板以包含a ContentPresenter.应该看起来像这样: -

public class MyWrapperPanel : ContentControl
{
    public MyWrapperPanel ()
    {
        this.DefaultStyleKey = typeof(MyWrapperPanel );
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在themes/generic.xaml中,样式可能如下所示: -

<Style TargetType="local:MyWrapperPanel">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:MyWrapperPanel">
                <Grid>
                    <ContentPresenter />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
Run Code Online (Sandbox Code Playgroud)

你的主页xaml看起来像: -

<my:MyWrapperPanel x:Name="myWrap">
    <TextBlock x:Name="tbxNothing" Text="Nothing" />
</my:MyWrapperPanel>
Run Code Online (Sandbox Code Playgroud)

请注意,派生自然ContentControl会为您提供自动神奇地连接的Content属性ContentPresenter.