2020-05-18

WPF 利用附加属性实现事件参数传递和引发

WPF 利用附加属性实现事件参数传递和引发


过程很简单,传递ViewModel到附加属性,附加属性引发相关事件和取消事件,从而引发VM中的委托。

 public class Attach {  private static DependencyObject ElementUI;  private static object Source;  private static string SourceName;  private static string EventName;  private static Delegate dlg;  public static readonly DependencyProperty EventNameProperty = DependencyProperty.RegisterAttached("EventName", typeof(string), typeof(Attach), new PropertyMetadata(null, new PropertyChangedCallback(OnEventNameValueChanged)));  public static void SetEventName(DependencyObject d, object value) => d.SetValue(EventNameProperty, value);  public static string GetEventName(DependencyObject d) => (string)d.GetValue(EventNameProperty);  private static void OnEventNameValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)  {   if (!e.NewValue.Equals(EventName))    EventName = e.NewValue.ToString();  }  public static readonly DependencyProperty PushAttachProperty = DependencyProperty.RegisterAttached("PushAttach", typeof(bool), typeof(Attach), new PropertyMetadata(false, new PropertyChangedCallback(OnPushAttachValueChanged)));  public static void SetPushAttach(DependencyObject d, bool value) => d.SetValue(PushAttachProperty, value);  public static bool GetPushAttach(DependencyObject d) => (bool)d.GetValue(PushAttachProperty);     private static void OnPushAttachValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)  {   if ((bool)e.NewValue == true)    DoAcion();   if ((bool)e.NewValue == false)    UnDoAcion();  }     private static void UnDoAcion()  {   var uisource = ElementUI.GetType();   var mothod = uisource.GetEvent(EventName);   mothod.RemoveEventHandler(ElementUI, dlg);   var getsource = Source.GetType();   var sourcemothod = getsource.GetProperty(SourceName).GetValue(Source) as Action<object, EventArgs>;   sourcemothod = null;  }  private static void DoAcion()  {   var getsource = ElementUI.GetType();   var mothod = getsource.GetEvent(EventName);   var k = Activator.CreateInstance(typeof(Attach));   var local = k.GetType().GetMethod(nameof(EventMethod),BindingFlags.Public|BindingFlags.Instance);    dlg = Delegate.CreateDelegate(mothod.EventHandlerType, k, local);   mothod.AddEventHandler(ElementUI, dlg);  }  public void EventMethod(object sender, EventArgs e)  {   var getsource = Source.GetType();   var mothod = getsource.GetProperty(SourceName).GetValue(Source) as Action<object, EventArgs>;   mothod?.Invoke(sender, e);     }  public static readonly DependencyProperty SourceProperty = DependencyProperty.RegisterAttached("Source", typeof(object), typeof(Attach), new PropertyMetadata(null, new PropertyChangedCallback(OnSourceValueChanged)));  public static void SetSource(DependencyObject d, object value) => d.SetValue(SourceProperty, value);  public static object GetSource(DependencyObject d) => (object)d.GetValue(SourceProperty);  private static void OnSourceValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)  {   if(ElementUI!=d)   ElementUI = d;   if(Source!=e.NewValue)   Source = e.NewValue;  }  public static readonly DependencyProperty SourceNameProperty = DependencyProperty.RegisterAttached("SourceName", typeof(string), typeof(Attach), new PropertyMetadata(null, new PropertyChangedCallback(OnSourceNameValueChanged)));  private static void OnSourceNameValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)  {   if(e.NewValue!=null)   if (!e.NewValue.Equals(SourceName))    SourceName = e.NewValue.ToString();  }  public static void SetSourceName(DependencyObject d, object value) => d.SetValue(SourceNameProperty, value);  public static string GetSourceName(DependencyObject d) => (string)d.GetValue(SourceNameProperty); }

 

xaml

<Button Height="120" VerticalAlignment="Top" Content="click" x:Name="b1" local:Attach.Source="{Binding RelativeSource={RelativeSource Mode=Self},Path=DataContext}" local:Attach.EventName="Click" local:Attach.SourceName="OnEvent" local:Attach.PushAttach="{Binding ElementName=cb1,Path=IsChecked}"/>
<CheckBox Height="120" Content="click" x:Name="cb1" IsChecked="False" />

 

ViewMode中放置一个委托即可

 public class VMTest: INotifyPropertyChanged {  protected void OnValueChanged(string Name) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(Name));  public event PropertyChangedEventHandler PropertyChanged;    public Action<Object,EventArgs> OnEvent { get; set; }  public VMTest()  {   OnEvent =new Action<Object,EventArgs>(OnEvent);  }  private void OnEvent(object arg1, EventArgs arg2)  {   MessageBox.Show("click");  } }

 

 

 

效果图


No comments:

Post a Comment