【问题标题】:How to know when binding has updated on dependency property如何知道绑定何时更新依赖属性
【发布时间】:2014-02-02 22:28:00
【问题描述】:

我正在创建一个具有依赖属性的自定义控件,我希望将自定义类绑定到该控件。当属性得到更新时,我想调用一个方法,以便它可以重新配置控件......我迷路了。

 internal partial class CollectionScheduleDayView : Canvas
    {
        public static DependencyProperty AppointmentsCollectionProperty = DependencyProperty.Register( "Collection", typeof( AppointmentCollections ), typeof( CollectionScheduleDayView ), new PropertyMetadata( null, PropertyChangedCallback ) );


        private static void PropertyChangedCallback( DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e )
        {
            SetDataContext( dependencyObject, e );
        }

        public AppointmentCollections Collection
        {
            get
            {
                return GetValue( AppointmentsCollectionProperty ) as AppointmentCollections;
            }
            set
            {
                SetValue( AppointmentsCollectionProperty, value );
            }
        }

        public CollectionScheduleDayView()
        {
            InitializeComponent();
        }

        void CollectionScheduleDayView_DataContextChanged( object sender, DependencyPropertyChangedEventArgs e )
        {

        }


        private static void SetDataContext( DependencyObject control, DependencyPropertyChangedEventArgs e )
        {
            var dayView = control as CollectionScheduleDayView;

            if (e.NewValue != null)
            {
                if (dayView != null)
                {
                   dayView.Collection = e.NewValue as AppointmentCollections;
                   dayView.DataContext = dayView.Collection;
                   dayView.SetupControl();
                }
            }
        }

        public void SetupControl()
        {
            ResetControl();

            Collection.RescheduledAppointments.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler( RescheduledAppointments_CollectionChanged );
            Collection.CompletedAppointments.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler( CompletedAppointments_CollectionChanged );
            Collection.RemainingAppointments.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler( RemainingAppointments_CollectionChanged );

            if (Collection.RescheduledAppointments == null || Collection.RescheduledAppointments.Count == 0)
            {
                CollapseRescheduled();
            }
            if (Collection.CompletedAppointments == null ||Collection.CompletedAppointments.Count == 0)
            {
                CollapseCompleted();
            }
        }

        //...some other code below 
}

我绑定到我的属性就好了:

<my:CollectionScheduleDayView Grid.Column="0" HorizontalAlignment="Left" Margin="12,35,0,0" x:Name="DayView0" VerticalAlignment="Top" Collection="{Binding DayOneAppointmentCollections, NotifyOnSourceUpdated=True}" SourceUpdated="CollectionScheduleDayView1_OnSourceUpdated"/>

PropertyChangedCallback 只被调用一次,不再调用该方法来更新控件;但是,绑定正在更新,并且当源更新时,属性也会更新...在我的视图模型中也不会调用 onpropertychanged()。

当我通过重新实例化绑定到我的控件的对象来强制在我的视图模型中调用 onpropertychanged() 时 - 绑定工作一次,但当属性更改时它不会更新,即使 onpropertychanged() 正在被调用。

我应该如何知道绑定何时更新?我的依赖属性代码是否正确?

【问题讨论】:

  • 请注意,您的 PropertyChangedCallback 用于 AppointmentsCollectionProperty,它包含对集合的引用。当然,更改该属性意味着更改引用,也就是将另一个集合对象分配给它。如果您没有为该属性分配另一个集合对象(或 null),那么该属性显然不会改变......如果您想知道集合本身是否发生了某些变化,那么您将不得不订阅相应的该集合的事件(ObservableCollection 提供了这样的事件)。
  • 在上面的代码中我这样做:Collection.RescheduledAppointments.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler( RescheduledAppointments_CollectionChanged ); 其中Collection.RescheduledAppointments 是一个 ObservableCollection - 这不起作用...
  • 好的,然后更具体地说明您的问题场景:如果您向添加了 CollectionChanged 处理程序的集合对象添加/删除项目,是否不会触发 CollectionChanged?还是您的问题是您不知道何时(例如)将 Collection.RescheduledAppointments 设置为另一个 ObservableCollection?根据您的问题,尚不清楚您的问题到底是什么/在哪里。
  • 两种方法都试过了,都没有效果
  • 两者?那是两个完全不同的话题。对于 CollectionChangedHandler:您的问题是处理程序被再次删除(您没有意识到它 - 查看您的代码),或者您订阅的特定 ObservableCollection 对象没有添加/删除项目(但是而是另一个 ObservableCollection 对象)。第二个主题是关于 AppointmentCollections 属性的更改:为 AppointmentCollections 类实现 INotifyPropertyChanged 接口,并订阅其 PropertyChanged 事件。

标签: c# wpf dependency-properties


【解决方案1】:

那里有一些我觉得不对劲的地方。

1 这不是必需的,因为绑定会为您执行此操作。如果在此处设置断点,您应该会看到 dayView.Collection 和 e.NewValue 已经相同。

dayView.Collection = e.NewValue as AppointmentCollections;

2 这也不是必需的。我认为这可能是罪魁祸首,因为您将 DataContext 更改为“DayOneAppointmentCollections”不再存在的位置。

dayView.DataContext = dayView.Collection;

3 在 SetupControl 中,请务必取消订阅旧集合。

【讨论】:

  • 基于接受,不设置DataContext对你有用吗?
  • 它是三者的结合——我认为它更能解除事件的附加。考虑到您可以使用 relativesource 绑定到控件,不设置数据上下文似乎很容易解决——我仍在努力实现这一点——但这将是一个不同的问题......你和@elgonzo 都给了好建议
  • 我使用(而不是使用RelativeSource)进行绑定的一个技巧是命名控件的根,然后在绑定中使用ElementName。 ... ...
  • 因此,如果名称类似于 Canvas1,我可以使用 ElementName=Canvas1.Collection.RemainingAppointments - 我将不得不考虑使用它 - 谢谢
  • 关闭。它将是“{Binding ElementName=Canvas1, Path=Collection.RemainingAppointments}”。如果您有类似 ReSharper 的东西可以在 XAML 中进行智能感知,那么您可以在设置 ElementName 绑定后看到这些属性。
猜你喜欢
  • 1970-01-01
  • 2011-12-18
  • 1970-01-01
  • 2011-03-05
  • 2011-07-31
  • 2020-08-06
  • 2013-03-22
  • 1970-01-01
  • 2016-08-28
相关资源
最近更新 更多