2023年7月19日发(作者:)
WPF关于MVVM事件绑定的多参传递问题
本文档主要讲关于MVVM事件绑定方式的实现,数据部分上的绑定暂时不提了。
原有调用方法:
CommandParameter="{Binding ElementName=gd_img}"/> Text="{Binding HangerName,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/> 该代码部分实现的是把MouseLeftButtonDown事件绑定到了ImgClickCommand命令下,并把gd_img这个Grid传递过去。一般情况下传递一个参数或者不传可以满足大多情况,但针对情况复杂的交互处理一个参数的传递已经不足以满足我们的需求。下面提供两个实现方案来解决这一问题。 第一种方式:重写InvokeCommandAction来扩充返回的参数 public class EventToCommand : TriggerAction { private string commandName; public readonly static DependencyProperty CommandProperty = er("Command", typeof(ICommand), typeof(EventToCommand), null); public readonly static DependencyProperty CommandParameterProperty = er("CommandParameter", typeof(object), typeof(EventToCommand), new PropertyMetadata(null, (DependencyObject s, DependencyPropertyChangedEventArgs e) => { EventToCommand sender = s as EventToCommand; if (sender == null) return; if (atedObject == null) return; })); /// /// 获取或设置此操作应调用的命令。这是依赖属性。 /// /// /// public ICommand Command { get{ return (ICommand)ue(dProperty);} set{ ue(dProperty, value); } } /// /// 获得或设置命令参数。这是依赖属性。 /// /// /// public object CommandParameter { get{return ue(dParameterProperty); } set{ ue(dParameterProperty, value); } } /// /// 获得或设置此操作应调用的命令的名称。 /// /// /// public string CommandName { get { eamble(); return dName; } set { if (dName != value) { reamble(); dName = value; ostscript(); } } } /// /// 调用操作。 /// /// 操作的参数。如果操作不需要参数,则可以将参数设置为空引用。 protected override void Invoke(object parameter) { if (atedObject == null) return; ICommand command = eCommand(); //注意这里添加了事件触发源和事件参数 ExCommandParameter exParameter = new ExCommandParameter { Sender = atedObject, //Parameter = GetValue(CommandParameterProperty), Parameter = dParameter, EventArgs = parameter as EventArgs }; if (command != null && cute(exParameter)) //将扩展的参数传递到Execute方法中 e(exParameter); } private ICommand ResolveCommand() { if (d != null) return d; if (atedObject == null) return null; ICommand result = null; Type type = e(); PropertyInfo[] properties = perties(ce | ); for (int i = 0; i < ; i++) { PropertyInfo propertyInfo = properties[i]; if (typeof(ICommand).IsAssignableFrom(tyType) && (, dName, l)) { result = (ICommand)ue(atedObject, null); break; } } return result; } } public class ExCommandParameter : object { /// /// 事件触发源 /// public DependencyObject Sender { get; set; } /// /// 事件参数 /// public EventArgs EventArgs { get; set; } /// /// 额外参数 /// public object Parameter { get; set; } } EventToCommand 类是我通过反编译系统类仿照着来写的,基本变化不大,改动体现在invoke方法里,对返回的参数进行了打包(把数据封装成了类) ExCommandParameter 类就是我们扩充的数据类,界面上的调用方式为 CommandParameter ="{Binding ElementName=sampleViewBox}"/> loc是EventToCommand 类所在的命名空间,可自己定义,要在xaml里添加声明方可使用。 后台使用方法: 首先需要在ViewModel里进行命令绑定的初始化,如: StretchSelectionChangedCommand = new DelegateCommand() { ExecuteActionObj = new Action 具体实现方式要根据自己编写的DelegateCommand类来决定 绑定的StretchSelectionChanged方法实现如下: private void StretchSelectionChanged(object obj) { ComboBox cbStretch = ((ExCommandParameter)obj).Sender as ComboBox; Viewbox sampleViewBox = ((ExCommandParameter)obj).Parameter as Viewbox; if (edItem != null) h = (edItem as StretchModel).theStretchMode; } 第二种方式:运用Behavior来实现事件,再运用视图树VisualTree来找所需的父控件或者子控件(控件到手了,就可以取到所需的参数),或者通过写依赖属性的方式来获取控件,以下Demo是通过写依赖属性来实现的 界面上调用: Margin="0,24,57,66" Width="30" Orientation="Vertical" Height="150"> TargetViewBox="{Binding ElementName=sampleViewBox}"/> 同样的我们需要引入behav这个命名空间来使用我们的SliderBehavior 类 后台实现如下: class SliderBehavior : Behavior { public readonly static DependencyProperty TargetGridProperty = er("TargetGrid", typeof(Grid), typeof(SliderBehavior), null); public readonly static DependencyProperty TargetViewBoxProperty = er("TargetViewBox", typeof(Viewbox), typeof(SliderBehavior), null); /// /// 这是依赖属性。 /// /// /// public Grid TargetGrid { get { return (Grid)ue(GridProperty); } set { ue(GridProperty, value); } } public Viewbox TargetViewBox { get{ return (Viewbox)ue(ViewBoxProperty); } set{ ue(ViewBoxProperty, value); } } protected override void OnAttached() { ched(); hanged += new RoutedPropertyChangedEventHandler } protected override void OnDetaching() { ching(); hanged -= HSlider_ValueChanged; } void HSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs { if ( == "HSlider") = Width * / 100.0; else = Height * / 100.0; } } Ps:看的时候可以忽略事件的实现类容,具体看下实现流程与调用方式。 意义: 我们可以看下Window类里的内容 public MainWindow() { InitializeComponent(); ntext = new MyViewModel(); } 没错,只有这些内容,剩下的实现都在ViewModel里,实现了数据,界面,业务逻辑的解耦。 That is all.
发布者:admin,转转请注明出处:http://www.yc00.com/news/1689723249a281189.html
评论列表(0条)