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