1.写一个命令处理函数要写一大堆的花花架子,例如
1 public ICommand WindowCloseCommand 2 { 3 get 4 { 5 return new RelayCommand(() => 6 { 7 //这里才是自己的代码,外面嵌套的太罗嗦了 8 } 9 ); 10 } 11 }
2.写Model类
1 private string money; 2 3 public string Money 4 { 5 get { return money; } 6 set { money = value; RaisePropertyChanged(() => Money); } 7 }
3.xaml命令比较臃肿
1 <i:Interaction.Triggers> 2 <i:EventTrigger EventName="MouseMove"> 3 <i:InvokeCommandAction Command="{Binding xxxCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" /> 4 </i:EventTrigger> 5 </i:Interaction.Triggers>
4.界面涉及复杂的元素操作,例如焦点相关的获取,失去,新开窗体什么的都比较麻烦。有没有那个框架封装度比较高的,能解决这些问题。例如vue的双向绑定就很简约。
没错,即使使用了 mvvm 框架,该模式还是显得繁琐,mvvm 模式很重要的优点是单元测试,如果项目小,其实没啥使用的必要,爱怎么写怎么写。
不过还是有解决方法的!
Q:如何消除 Model 中繁琐的属性通知代码?
A:使用 Fody 旗下的 Fody/ropertyChanged
基本使用方法:在 Model 类名上添加 [AddINotifyPropertyChangedInterface] 特性,该类的所有属性便全部拥有了通知功能。
Q:如何消除命令模式前后端的繁琐代码?
A:mvvm 框架 Caliburn.Micro 也许能帮你,该框架与 mvvmlight 不同,它基于名称约定,也就是说,如果你有个名为 “GetData” 的按钮,vm 中有个名为 “GetData()” 的方法,那么这个按钮就自动将命令绑定到了 GetData() 方法。
另一个推荐的 mvvm 框架是 Stylet,它是由 Caliburn.Micro 改造而来,提供了更多简化操作。
补充推荐一个 mvvm 框架:Catel,也具有自动映射从模型到视图模型的功能。
以上具体使用方法,可以自行搜索教程。
非常感谢,我去试试
你好,stylet怎么实现事件转命令呢,mvvmlight中可以使用cmd命名空间的eventtocommand,stylet中怎么响应例如textbox的keyup,mousedown之类的事件呢
@屋檐不懂雨: 命令和事件都一样:
<Button Command="{s:Action DoSomething}" CommandParameter="Hello">Click me</Button>
public void DoSomething() { } public void DoSomething(EventArgs e) { } public void DoSomething(object sender, EventArgs e) { }
@CodingNinja: 不是这种,例如textbox我想要在keydown事件中获取按下键的字符信息,这种要怎么写,直接传参会的
@CodingNinja: 尝试了下这样写,但是发现按字母键无法触发keydown事件,只有ctrl,shift,alt能触发
<TextBox Margin="307,61,285.6,310" KeyDown="{s:Action keydown}" Text="{Binding UserModel.UserPwd}" />
@屋檐不懂雨: 你后台事件处理函数怎么写的?
@CodingNinja:
public void keydown(object sender, KeyEventArgs e) { }
@屋檐不懂雨: 不得而知,试试 PreviewKeyDown 事件
@CodingNinja: 试过了,也不行.如果这样的话其实stylet框架并不成熟,windows上的稍微复杂点的操作都没法搞呀,或者复杂操作不用stylet
@屋檐不懂雨: 我帮你在 GitHub 问了,等结果吧。
@CodingNinja: 好的,多谢
@屋檐不懂雨: 但是,你为什么需要 KeyDown 事件?
@CodingNinja:
有时候要对用户输入的东西做些判断处理,例如一个textbox金额框,不能输入非法字符之类的.还有一些特殊的操作会需要mousedown,mouseup之类的事件
@屋檐不懂雨: wpf 有很多数据校验方式,不需要 KeyDown 啊,比如你可以把绑定触发模式设置为 UpdateSourceTrigger=PropertyChanged ,发生变化就触发判断。
@CodingNinja: 公司做的程序是那种工具类的,操作交互比较复杂,不是单纯的界面展示数据.还有一些mousedown,mouseup触发的事件都比较多
问题尖锐奥,插眼
我在看aop的时候看到了一种aop的写法:
[Mixin(typeof(INotifyPropertyChanged))]
[Aspect(Scope.PerInstance)]
internal class NotifyAspect : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = (s, e) => { };
[Advice(Kind.After, Targets = Target.Public | Target.Setter)]
public void AfterSetter(
[Argument(Source.Instance)] object source,
[Argument(Source.Name)] string propName,
[Argument(Source.Injections)] Attribute[] injections
)
{
PropertyChanged(source, new PropertyChangedEventArgs(propName));
foreach(var i in injections.OfType<Notify>().ToArray())
PropertyChanged(source, new PropertyChangedEventArgs(i.NotifyAlso));
}
}
对应的属性就可以简单些了:
[Notify(NotifyAlso = nameof(Fullname))]
public string FirstName
{
get;
set;
}
[Notify(NotifyAlso = nameof(Fullname))]
public string LastName
{
get;
set;
}
MouseMove需要事件转命令,按钮啥的并不需要这么麻烦。我们都没用过什么框架,自己稍微封装了下。
只有个别控件有command命令,其他大部分控件都要这样写
Button_Click
事件绑定命令确实代码冗余,可以试试自定义Behavior或MarkupExtension,这是源代码:https://github.com/LeoYang-Chuese/wif ,比Blend的方式要简单。
第一种:EventToCommandBehavior。
<Wif.Demo:ListBox x:Name="ListBox" ItemsSource="{Binding ListBoxItems}">
<wif:EventToCommandBehavior.EventBindings>
<Wif:EventBinding Command = "{Binding CustomCommand}" EventName="MouseEnter" />
</Wif:EventToCommandBehavior.EventBindings>
</Wif.Demo:ListBox>
第二种:EventBindingExtension。
<Rectangle MouseDown="{wif:EventBinding MouseDownCommand}" /> 普通无参数绑定。
<Rectangle MouseDown="{wif:EventBinding Command=MouseDownCommand, CommandParameter=blue}" /> 普通绑定。
<Rectangle MouseDown="{wif:EventBinding Command=MouseDownCommand, CommandParameter=$this.Fill}" /> 绑定到当前控件的属性上。
<Rectangle MouseDown="{wif:EventBinding Command=MouseDownCommand, CommandParameter=$e}" /> 绑定到当前上下文上。
你好,那eventtocommand怎么写呢,vm中怎么接收事件参数呢
@屋檐不懂雨:
第一种:
<Wif.Demo:ListBox x:Name="ListBox" ItemsSource="{Binding ListBoxItems}">
<wif:EventToCommandBehavior.EventBindings>
<Wif:EventBinding Command = "{Binding CustomCommand}"
EventName="MouseEnter"
CommandParameter="MyParameter"/>
</Wif:EventToCommandBehavior.EventBindings>
</Wif.Demo:ListBox>
第二种方式是自定义的,如你所见,某些参数前面需要加 $ 符号。