我创建了一个用户控件,我将其重用用于不同目的。我已经定义了一个包含UIElement的依赖属性,我将其作为用户控件中某个区域的内容呈现。
当我使用此控件时,我注意到了。并为content属性中的元素指定名称,它们在运行时始终显示为null。
MyContainer.xaml:
<UserControl x:Class="BSSApp.UI.Tests.MyContainer" x:Name="userControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Border x:Name="LayoutRoot" Background="Green" CornerRadius="20" BorderBrush="#005500" BorderThickness="10">
<ContentPresenter Content="{Binding ElementName=userControl, Path=MyContent}" Margin="20"/>
</Border>
</UserControl>
MyContainer.xaml.cs
namespace BSSApp.UI.Tests
{
public partial class MyContainer : UserControl
{
public static readonly DependencyProperty MyContentProperty =
DependencyProperty.Register("MyContent",
typeof(UIElement),
typeof(MyContainer),
new PropertyMetadata(new Grid()));
public UIElement MyContent
{
get
{
return (UIElement)GetValue(MyContentProperty);
}
set
{
SetValue(MyContentProperty, value);
}
}
public MyContainer()
{
InitializeComponent();
}
}
}
使用类: UserControlContentBug.xaml:
<UserControl x:Class="BSSApp.UI.Tests.UserControlContentBug"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:t="clr-namespace:BSSApp.UI.Tests"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<t:MyContainer>
<t:MyContainer.MyContent>
<Button Name="btnWithName" Click="btnWithName_Click">Click Me</Button>
</t:MyContainer.MyContent>
</t:MyContainer>
</Grid>
</UserControl>
和背后的代码: UserControlContentBug.xaml.cs
namespace BSSApp.UI.Tests
{
public partial class UserControlContentBug : UserControl
{
public UserControlContentBug()
{
InitializeComponent();
}
private void btnWithName_Click(object sender, RoutedEventArgs e)
{
// this throws an exception
btnWithName.Tag=2;
}
}
}
因此有一个名为“btnWithName”的按钮声明。该变量确实在后面的代码中声明,但它保持为null ...只有当按钮在另一个用户控件的属性中声明时才会发生。
有人知道如何解决这个问题吗?
由于
答案 0 :(得分:6)
我自己也遇到了这个问题。生成的部分类(例如,obj \ UserControlContentBug.xaml.g.cs)定义了XAML中代码可访问的命名元素,使用FrameworkElement.FindName()进行这些分配。
根据MSDN:
FindName等运行时API正在对对象树起作用。这些对象将加载到整个Silverlight插件的内容区域和CLR运行时引擎中。当从模板或运行时加载的XAML创建对象树的一部分时,XAML名称范围通常与该对象树的整体不连续。结果是对象树中可能存在命名对象无法找到给定的FindName调用。
由于MyContainer将自己的名称范围边界建立为UserControl,因此从UserControlContentBug调用FindName()将不会探索对象树的那一部分(其中) btnWithName已定义)。
可能有几种不同的方法可以解决这个问题,但对我来说最简单的方法是:
为MyContainer命名(x:Name="myContainer"
)。
从Button(btnWithName)中删除名称,以便在生成的C#代码中不保留同名的多余的always-null变量。
在代码隐藏中创建对Button的引用。
像这样:
namespace BSSApp.UI.Tests
{
public partial class UserControlContentBug : UserControl
{
private Button btnWithName;
public UserControlContentBug()
{
Loaded += UserControlContentBugLoaded;
InitializeComponent();
}
private void UserControlContentBugLoaded(object sender, System.Windows.RoutedEventArgs e)
{
btnWithName = myContainer.MyContent as Button;
}
private void btnWithName_Click(object sender, RoutedEventArgs e)
{
// this throws an exception, not so much
btnWithName.Tag=2;
}
}
}
希望这有帮助。
答案 1 :(得分:0)
尝试在按钮上使用x:Name而不是Name。