Silverlight监听属性变化

现有两个DataGrid:A、B,A是母表,B是子表。即B是A集合的一部分,当点击A的不同行时,B发生变化,列出选中行的详细。

简单来说,B的ItemsSource是不断变化的。那怎么监听B的ItemsSource呢,当ItemsSource变化时,有通知事件?首先想到的是依赖属性,但依赖属性只会跑一次,实现不了监听的功能。在谷歌上,找到一篇博客,实现我的功能。

http://blog.thekieners.com/2010/08/27/listening-to-dependencyproperty-changes-in-silverlight/

首先,要定义两个类。

DependencyPropertyChangedListener

View Code
  1 using System;

  2 using System.Windows;

  3 using System.Windows.Data;

  4 

  5 namespace Controls.Query.Helpers

  6 {

  7     /// <summary>

  8     /// This class implements a listener to receive notifications for dependency property changes.

  9     /// </summary>

 10     public class DependencyPropertyChangedListener

 11     {

 12         #region Inner types

 13 

 14         // Helper element to make it possible to use the binding engine to get notified when the source element property changes.

 15         private sealed class RelayObject : DependencyObject

 16         {

 17             private DependencyPropertyChangedListener _listener;

 18 

 19             internal RelayObject(DependencyPropertyChangedListener listener)

 20             {

 21                 _listener = listener;

 22             }

 23 

 24             #region Value (DependencyProperty)

 25 

 26             public object Value

 27             {

 28                 get { return (object)GetValue(ValueProperty); }

 29                 set { SetValue(ValueProperty, value); }

 30             }

 31             public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(RelayObject), new PropertyMetadata(default(object), new PropertyChangedCallback(OnValueChanged)));

 32 

 33             private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)

 34             {

 35                 object oldValue = (object)e.OldValue;

 36                 object newValue = (object)e.NewValue;

 37                 RelayObject source = (RelayObject)d;

 38                 source.OnValueChanged(oldValue, newValue);

 39             }

 40 

 41             private void OnValueChanged(object oldValue, object newValue)

 42             {

 43                 _listener.OnValueChanged(oldValue, newValue);

 44             }

 45 

 46             #endregion

 47         }

 48 

 49         #endregion

 50 

 51         #region Events

 52 

 53         /// <summary>

 54         /// Raises when the dependency property changes.

 55         /// </summary>

 56         public event EventHandler<DependencyPropertyValueChangedEventArgs> ValueChanged;

 57 

 58         #endregion

 59 

 60         #region Ctor

 61 

 62         private DependencyPropertyChangedListener()

 63         {

 64             // just to make it private

 65         }

 66 

 67         #endregion

 68 

 69         // holds a reference to the relay object in order that the GC does not collect it

 70         private RelayObject RelayInstance { get; set; }

 71 

 72         public static DependencyPropertyChangedListener Create(DependencyObject sourceElement, string propertyPath)

 73         //public static DependencyPropertyChangedListener Create(DependencyObject sourceElement, DependencyProperty property)

 74         {

 75             // check input

 76             if (sourceElement == null)

 77                 throw new ArgumentNullException("sourceElement");

 78             if (string.IsNullOrWhiteSpace(propertyPath))

 79                 throw new ArgumentException("propertyPath is empty");

 80 

 81             // create listener

 82             DependencyPropertyChangedListener listener = new DependencyPropertyChangedListener();

 83 

 84             // setup binding

 85             Binding binding = new Binding();

 86             binding.Source = sourceElement;

 87             binding.Mode = BindingMode.OneWay;

 88             //binding.Path = new PropertyPath(property); // throws exception

 89             binding.Path = new PropertyPath(propertyPath);

 90 

 91             // create relay object

 92             RelayObject relay = new RelayObject(listener);

 93             // ...the listener holds a reference to the relay object in order that the GC does not collect it

 94             listener.RelayInstance = relay;

 95 

 96             // set binding

 97             BindingOperations.SetBinding(relay, RelayObject.ValueProperty, binding);

 98 

 99             return listener;

100         }

101 

102         public void Detach()

103         {

104             if (this.RelayInstance != null)

105             {

106                 // first: reset member to prevent further eventing of ValueChanged event.

107                 RelayObject temp = this.RelayInstance;

108                 this.RelayInstance = null;

109 

110                 // second: clear the binding -> raises property changed event...

111                 temp.ClearValue(RelayObject.ValueProperty);

112             }

113         }

114 

115         private void OnValueChanged(object oldValue, object newValue)

116         {

117             // raise event, but only if the listener is not detached.

118             if (ValueChanged != null && this.RelayInstance != null)

119                 ValueChanged(this, new DependencyPropertyValueChangedEventArgs(oldValue, newValue));

120         }

121     }

122 }

 

DependencyPropertyValueChangedEventArgs,继承EventArgs

View Code
 1 using System;

 2 

 3 namespace Controls.Query.Helpers

 4 {

 5     /// <summary>

 6     /// Provides data for a DependencyPropertyChangedListener ValueChanged implementation.

 7     /// </summary>

 8     public class DependencyPropertyValueChangedEventArgs : EventArgs

 9     {

10         internal DependencyPropertyValueChangedEventArgs(object oldValue, object newValue)

11         {

12             OldValue = oldValue;

13             NewValue = newValue;

14         }

15 

16         /// <summary>

17         ///  Gets the value of the property before the change.

18         /// </summary>

19         public object OldValue { get; private set; }

20 

21         /// <summary>

22         /// Gets the value of the property after the change.

23         /// </summary>

24         public object NewValue { get; private set; }

25     }

26 }

 

在引用的地方这样写

 1 private DependencyPropertyChangedListener listener;

 2        

 3 public MainPage()

 4 {

 5     InitializeComponent();

 6 

 7     listener = DependencyPropertyChangedListener.Create(this, "BindingGrid.ItemsSource");

 8     listener.ValueChanged += ListenerValueChanged;

 9 }

10 

11 void ListenerValueChanged(object sender, DependencyPropertyValueChangedEventArgs e)

12 {

13      var itemsSource = BindingGrid.ItemsSource;

14             if (itemsSource != null)

15             {

16                 //SourceInitialized(itemsSource);

17             }

18 }

19 

20  public DataGrid BindingGrid

21         {

22             get { return (DataGrid)GetValue(BindingGridProperty); }

23             set { SetValue(BindingGridProperty, value); }

24         }

25 

26  public static readonly DependencyProperty BindingGridProperty =

27             DependencyProperty.Register("BindingGrid", typeof(DataGrid), typeof(ConfigurableQueryer),

28                                         new PropertyMetadata(null, OnBindingGridChange));

29 

30 //只跑一次

31  private static void OnBindingGridChange(DependencyObject sender, DependencyPropertyChangedEventArgs e)

32         {

33             var configurableQueryer = sender as ConfigurableQueryer;

34             var dg = e.NewValue as DataGrid;

35 }

 

你可能感兴趣的:(silverlight)