【问题标题】:User Control binding not working for nested property用户控件绑定不适用于嵌套属性
【发布时间】:2013-09-30 05:27:45
【问题描述】:

我有一个名为 InformationControl 的用户控件。我在我的窗口中使用它,如下所示:

<general:InformationControl Grid.Row="0" TimeToStart="{Binding TimeToStart}" Poor="{Binding Path=Mine.Poor}" Status="{Binding Path=Mine.MineStatus}"/>

TimeToStart 依赖属性上的绑定工作正常,但是当我使用 Path=Object.Property 时似乎不起作用。

但是,当我在常规控件(即不是 UserControl)上使用 Path=Object.Property 时,它可以正常工作:

<ItemsControl Grid.Row="2" Name="Items" ItemsSource="{Binding Path=Mine.Participants}">

我打破了 Mine 的 getter,在绑定日志中它说它是空的,但它肯定已经设置了。此外,它首先尝试获取该属性的事实让我觉得绑定是正确的,但我无法弄清楚它为什么不起作用。

我是否需要做一些不同的事情来确保嵌套属性的绑定适用于 UserControl 依赖属性?

【问题讨论】:

  • InformationControl 的 DataContext 是什么?我很困惑。在它工作的 ItemsControl 中,您尝试了 Mine.Participants,TimeToStart 在哪里?
  • InformationControl 的 DataContext 未设置。我认为这对于依赖属性不是必需的?我试图对 ItemsControl 提出的一点是 Path=Object.Property 正在工作,但它不适用于用户控件。谢谢!
  • 您能否检查设置属性的顺序以及您的用户控件何时使用 Mine.Property?您可能在用户控件已经开始加载后尝试设置它。
  • InformationControl 的 DataContext 是必要的,并且您期望名为 Mine 的属性位于该对象的数据上下文中,然后您可以执行嵌套属性。
  • @gavin 在用户控件已经开始加载之后尝试设置它并不重要,因为他正在执行绑定,因此它将更新值。

标签: c# wpf data-binding user-controls dependency-properties


【解决方案1】:

信息控制代码隐藏,在Debug.Print("newvalue...")处设置断点

namespace WpfStackoverflow
{
    /// <summary>
    /// Interaction logic for InformationControl.xaml
    /// </summary>
    public partial class InformationControl : UserControl
    {
        public static readonly DependencyProperty TimeToStartProperty;
        static InformationControl()
        {
            //FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata("");
            TimeToStartProperty = DependencyProperty.Register("TimeToStart", typeof(string), typeof(InformationControl), new UIPropertyMetadata(string.Empty, UsernamePropertyChangedCallback));
        }

        public string TimeToStart
        {
            get { 
                return (string)GetValue(TimeToStartProperty); 
            }
            set { 
                SetValue(TimeToStartProperty, value); 
            }
        }

        public InformationControl()
        {
            InitializeComponent();
            string temp = TimeToStart;

        }
        private static void UsernamePropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Debug.Print("OldValue: {0}", e.OldValue);
            Debug.Print("NewValue: {0}", e.NewValue);
        }
    }
}

主窗口 xaml:

<Window x:Class="WpfStackoverflow.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfStackoverflow"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <local:InformationControl TimeToStart="{Binding Mine.Name}" />

    </Grid>
</Window>

后面的主窗口代码:

namespace WpfStackoverflow
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Parent p = new Parent();
            p.Mine = new Mine();
            p.Mine.Name = "Hello world";
            this.DataContext = p;
        }
    }
}

父类:

namespace WpfStackoverflow
{


    public class Parent:INotifyPropertyChanged
    {
        private Mine _mine;
        public Mine Mine
        {
            get
            {
                return _mine;
            }
            set
            {
                _mine = value;
                NotifyPropertyChanged();
            }
        }
        private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }
    public class Mine : INotifyPropertyChanged
    {
        private string _name;
        public string Name { get { return _name; }
            set
            {
                _name = value;
                NotifyPropertyChanged();
            }
        }
        private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }

}

我真的不知道您要完成什么,但是如果您查看我的示例,如果您在 InformationControl 的依赖项属性更改回调中设置断点,则获取 Mine.Name 可以在用户控件中工作。另请注意,setter 永远不会被调用,因为 clr 绕过 setter 并直接调用 setvalue。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-03
    • 2012-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多