x:如果元素包含在UserControl的内容中(Silverlight),则名称不起作用
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了x:如果元素包含在UserControl的内容中(Silverlight),则名称不起作用相关的知识,希望对你有一定的参考价值。
情况:
我有一个像这样的“包装器面板”UserControl
(为简洁起见,删除了名称空间和视觉细节):
<UserControl ...>
<Grid x:Name="LayoutRoot" Background="White">
<ContentPresenter x:Name="integratedPanelContent" Margin="5" />
</Grid>
</UserControl>
然后在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;
}
现在我可以将任何内容包装到我的控件中:
<my:MyWrapperPanel x:Name="myWrap">
<my:MyWrapperPanel.PanelContent>
<TextBlock x:Name="tbxNothing" Text="Nothing" />
</my:MyWrapperPanel.PanelContent>
</my:MyWrapperPanel>
问题描述:
每当我尝试在代码隐藏中使用引用tbxNothing时,系统抛出NullReferenceException
,因为tbxNothing虽然作为引用存在,但并不指向XAML中定义的TextBlock,而是null
。
可能(但不方便)的解决方法:
有一种解决方法,我从TextBlock中删除x:Name
,然后我明确定义名为tbxNothing
的私有TextBlock。然后在OnNavigatedTo
事件处理程序中,我按以下方式分配值:
tbxNothing = myWrap.PanelContent as TextBlock;
这可行,但不是一种正确的方法,因为如果内容是包含所需控件的堆栈面板,我必须遍历树以找到我需要的东西,这非常不方便。
题:
为什么在用户控件(描述的方式)中包装时文本块不再可见,以及如何通过其代码隐藏中的x:Name来获取它?
问题是你的面板内容在两个凳子之间下降。一方面,名称为“tbxNothing”的内容是在主页面的名称范围内创建的。但是,此时它未添加到对象树中。另一方面,作为UserControl的MyWrapperPanel具有自己的名称范围,并且在其下面的对象树中添加了具有名称“tbxNothing”的项目。主页面上的FindName
在MyWrapperPanel中找不到任何内容,因为它有自己的名称范围,而MyWrapperPanel上的FindName
将找不到“tbxNothing”,因为它在名称范围内不存在(实际上是在主页面中创建的)。
答案是不要使用UserControl
作为MyWrapperPanel
的基础。而是创建一个Silverlight模板控件。将它继承的基类修改为ContentControl
并调整其默认模板以包含ContentPresenter
。应该看起来像这样: -
public class MyWrapperPanel : ContentControl
{
public MyWrapperPanel ()
{
this.DefaultStyleKey = typeof(MyWrapperPanel );
}
}
然后在themes / generic.xaml中,样式可能如下所示: -
<Style TargetType="local:MyWrapperPanel">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MyWrapperPanel">
<Grid>
<ContentPresenter />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
你的主页xaml看起来像: -
<my:MyWrapperPanel x:Name="myWrap">
<TextBlock x:Name="tbxNothing" Text="Nothing" />
</my:MyWrapperPanel>
请注意,从ContentControl
派生出一个Content
属性,ContentPresenter
自动神奇地连接到。
以上是关于x:如果元素包含在UserControl的内容中(Silverlight),则名称不起作用的主要内容,如果未能解决你的问题,请参考以下文章
UserControl 的内容属性内的命名控件在运行时始终显示为空
WPF怎么修改在窗体里引用的UserControl中元素的值?