WPF 实现 ItemsControl.ItemsSourceChanged 事件的变通方法

WPF,ListBox的ItemsSource更改事件
在WPF中,一个ListBox的ItemsSource的值发生更改,这个更改事件是什么?
------解决思路----------------------
没有正式的ItemsSourceChanged事件。
你可以继承ListBox,并重载OnItemsSourceChanged方法,
或者更简单的,利用ItemsSourse是依赖属性的特点,登记你自己的改变处理:

var dpd = DependencyPropertyDescriptor.FromProperty(ListBox.ItemsSourceProperty, typeof(ListBox));

dpd.AddValueChanged(listBox1,
 (o, e) => { MessageBox.Show("items souce changed."); });

 

以下是周银辉提供的一个演示demo:

    public class People : DependencyObject
    {
        public static readonly DependencyProperty NameProperty =
            DependencyProperty.Register("Name", typeof (string), typeof (People), new PropertyMetadata(default(string)));

        public string Name
        {
            get { return (string) GetValue(NameProperty); }
            set { SetValue(NameProperty, value); }
        }
    }

//.........
        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            var people = new People {Name = "zhang san"};

            var descriptor =  DependencyPropertyDescriptor.FromProperty(People.NameProperty, typeof (People));
            descriptor.AddValueChanged(people, (o, args) => MessageBox.Show("name changed to " + people.Name));

            people.Name = "Li si";
        }

以下代码来自:

https://social.msdn.microsoft.com/Forums/vstudio/en-US/969a88f2-a834-4443-8c32-e656052db945/listview-itemssource-changed-event?forum=wpf

TypeDescriptor.GetProperties(listviewcontrol)["ItemsSource"].AddValueChanged(listviewcontrol, new EventHandler(ListView_ItemsSourceChanged));

 

阅读微软的源代码文档中的注释对理解 FromProperty 方法大有帮助:

/// <summary>
///     Static method that returns a DependencyPropertyDescriptor from a DependencyProperty.  The
///     DependencyProperty may refer to either a direct or attached property.  The targetType is the
///     type of object to associate with the property:  either the owner type for a direct property
///     or the type of object to attach to for an attached property.
/// </summary>
        internal static DependencyPropertyDescriptor FromProperty(
      DependencyProperty dependencyProperty,
      Type ownerType,
      Type targetType,
      bool ignorePropertyType)
      // We have a different codepath here for attached and direct
          // properties.  For direct properties, we route through Type
          // Descriptor because we need the underlying CLR property descriptor
          // to create our wrapped property.  For attached properties, all we
          // need is the dp and the object type and we can create an attached
          // property descriptor based on that.  We must special case attached
          // properties here because TypeDescriptor will only return attached
          // properties for instances, not types.
        /// <summary>
        ///     Static method that returns a DependencyPropertyDescriptor for a given property name.
        ///     The name may refer to a direct or attached property.  OwnerType is the type of 
        ///     object that owns the property definition.  TargetType is the type of object you wish
        ///     to set the property for.  For direct properties, they are the same type.  For attached
        ///     properties they usually differ.
        /// </summary>
        public static DependencyPropertyDescriptor FromName(string name, Type ownerType, Type targetType,
            bool ignorePropertyType)

 

以上只是提供了变通解决方案,但是仔细思考一下:

ItemsSourceChanged 事件有存在的意义吗?

ItemsSource 依赖项属性要么为null,要么就被绑定到一个IEnumerable类型的属性;

除非手动对ItemsSource赋值(一般不会用这么笨的办法),否则,直接在绑定源的set访问器中引发ItemsSourceChanged事件(可以是CLR事件,也可以是路由事件)就行了。

posted @ 2018-09-22 17:06  JolinPiggy  阅读(1443)  评论(0)    收藏  举报