UserControl的内容属性中的命名控件在运行时始终显示为null

Kob*_*ari 7 silverlight user-controls

我创建了一个用户控件,我将其用于不同的目的.我已经定义了一个包含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>
Run Code Online (Sandbox Code Playgroud)

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

而使用类: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>
Run Code Online (Sandbox Code Playgroud)

和后面的代码: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;
         }
     }
  }
Run Code Online (Sandbox Code Playgroud)

因此,有一个名为"btnWithName"的按钮声明.该变量确实在后面的代码中声明,但它保持为null ...只有当按钮在另一个用户控件的属性中声明时才会发生.

有人知道如何解决这个问题吗?

谢谢

Lee*_*nau 6

我自己也遇到了这个问题.生成的部分类(例如,obj\UserControlContentBug.xaml.g.cs)定义了XAML中代码可访问的命名元素,它使用FrameworkElement.FindName()来进行这些分配.

根据MSDN:

诸如FindName之类的运行时API正在对对象树起作用.这些对象将加载到整个Silverlight插件的内容区域和CLR运行时引擎中.当从模板或运行时加载的XAML创建对象树的一部分时,XAML名称范围通常与该对象树的整体不连续.结果是对象树中可能存在命名对象无法找到给定的FindName调用.

由于MyContainer将自己的名称范围边界建立为UserControl,因此从UserControlContentBug调用FindName()将不会探索对象树的那一部分(其中定义了btnWithName).

可能有几种不同的方法可以解决这个问题,但对我来说最简单的方法是:

  1. 给MyContainer一个名字(x:Name="myContainer").

  2. 从Button(btnWithName)中删除名称,以便在生成的C#代码中不保留同名的多余的always-null变量.

  3. 在代码隐藏中创建对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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.


Phi*_*ler 0

尝试在按钮上使用 x:Name 而不是 Name。