惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

SecWiki News
SecWiki News
WordPress大学
WordPress大学
Martin Fowler
Martin Fowler
MyScale Blog
MyScale Blog
Project Zero
Project Zero
博客园 - 聂微东
Recorded Future
Recorded Future
MongoDB | Blog
MongoDB | Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Stack Overflow Blog
Stack Overflow Blog
T
The Exploit Database - CXSecurity.com
博客园 - 三生石上(FineUI控件)
C
CERT Recently Published Vulnerability Notes
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Engineering at Meta
Engineering at Meta
美团技术团队
Microsoft Azure Blog
Microsoft Azure Blog
C
Cisco Blogs
www.infosecurity-magazine.com
www.infosecurity-magazine.com
小众软件
小众软件
N
News and Events Feed by Topic
D
DataBreaches.Net
量子位
B
Blog RSS Feed
Apple Machine Learning Research
Apple Machine Learning Research
F
Fortinet All Blogs
博客园 - 司徒正美
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
T
Tailwind CSS Blog
Spread Privacy
Spread Privacy
Blog — PlanetScale
Blog — PlanetScale
M
MIT News - Artificial intelligence
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
C
Check Point Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
爱范儿
爱范儿
S
SegmentFault 最新的问题
人人都是产品经理
人人都是产品经理
C
CXSECURITY Database RSS Feed - CXSecurity.com
Hugging Face - Blog
Hugging Face - Blog
AI
AI
腾讯CDC
I
InfoQ
P
Palo Alto Networks Blog
G
Google Developers Blog
T
Threat Research - Cisco Blogs
T
Tenable Blog
Vercel News
Vercel News
Google Online Security Blog
Google Online Security Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - 天神一

Windows 8的本地化应用程序清单 代码滑动panorama-即程序中设置SelectedIndex WP7开发 Sqlite数据库的使用 解决Unable open the database WP7 真机调试PhotoChooserTask和CameraCaptureTask 解决windows8不能安装ZUNE的问题 软件概要设计 AutoResetEvent详解 解决VS2008 调试启动特别慢 微软WP7本地数据库之Sqlite编程技巧(转) 桥接模式的简单分析 代码的“门面”——模式系列谈之Facade模式(转) SilverLight4:在MVVM架构下实现模式窗口 简析SilverLight的List<T>、ObservableCollection<T>和INotifyPropertyChanged的异同 MVVM架构的简单解析 XNA 4.0新书:初学者很好的书籍 SilverLight:在MVVM中实现多事件 SilverLight:使用MVVM实现View层在程序运行时自动生成控件并且取得其值 (翻译)在MVVM模式中打开子窗体(Child Window) Windows Phone 7 完全版电子书可以免费下载了
在MVVM架构下,把EventArgs绑定到Command上【翻译】
天神一 · 2010-12-18 · via 博客园 - 天神一

  在使用MVVM架构时,我们会遇到各种各样的问题

  其中一个很常见的问题就是如何在ViewModel层处理UI事件时在后台代码文件中不写任何代码。

  在我这个例子中实现的是取得鼠标移动时的位置。

  我的解决方法如下:

  1、通过一个Behavior 取得关联对象的EventArgs,代码如下

 1 public class ExtendedInvokeCommandAction : TriggerAction<FrameworkElement>
 2     {
 3         public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command"typeof(ICommand), typeof(ExtendedInvokeCommandAction), new PropertyMetadata(null, CommandChangedCallback));
 4         public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter"typeof(object), typeof(ExtendedInvokeCommandAction), new PropertyMetadata(null, CommandParameterChangedCallback));
 5 
 6         private static void CommandParameterChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
 7         {
 8             var invokeCommand = d as ExtendedInvokeCommandAction;
 9             if (invokeCommand != null)
10                 invokeCommand.SetValue(CommandParameterProperty, e.NewValue);
11         }
12 
13         private static void CommandChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
14         {
15             var invokeCommand = d as ExtendedInvokeCommandAction;
16             if (invokeCommand != null)
17                 invokeCommand.SetValue(CommandProperty, e.NewValue);
18         }
19 
20         protected override void Invoke(object parameter)
21         {
22             if (this.Command == null)
23                 return;
24 
25             if (this.Command.CanExecute(parameter))
26             {
27                 var commandParameter = new ExtendedCommandParameter(parameter as EventArgs, this.AssociatedObject,
28                                                                     GetValue(CommandParameterProperty));
29                 this.Command.Execute(commandParameter);
30             }
31         }
32 
33         #region public properties
34 
35         public object CommandParameter
36         {
37             get { return GetValue(CommandParameterProperty); }
38             set { SetValue(CommandParameterProperty, value); }
39         }
40 
41         public ICommand Command
42         {
43             get { return GetValue(CommandProperty) as ICommand; }
44             set { SetValue(CommandParameterProperty, value); }
45         }
46 
47         #endregion
48     }

  2、写一个类,包含的属性有事件源、EventArgs和对象,代码如下

 1 public class ExtendedCommandParameter
 2     {
 3         public ExtendedCommandParameter(EventArgs eventArgs, FrameworkElement sender, object parameter)
 4         {
 5             EventArgs = eventArgs;
 6             Sender = sender;
 7             Parameter = parameter;
 8         }
 9 
10         public EventArgs EventArgs { getprivate set; }
11         public FrameworkElement Sender { getprivate set; }
12         public object Parameter { getprivate set; }
13     }

  3、为对象添加Behavior

  在我的这个例子中,我对Rectangle添加新建的类ExtendedInvokeCommandAction(即Behavior)

  4、在ViewModel层把这个Behavior绑定到Command上,在这Command上选择一个事件,通过Comman调用这个事件

  在我这个例子中,在ViewModle层我把MouseMove事件绑定到MouseMoved Command上,另外,如果需要的话,可以把任何对象绑定到CommandParameter,在我这个例子中,我把此View(变量名为userControl)绑定到了CommandParameter(不是必须的)

  

 1 
 2 <Rectangle Fill="#FF9B9BC5" Height="200" Stroke="Black" Width="200">
 3             <i:Interaction.Triggers>
 4                 <i:EventTrigger EventName="MouseMove">
 5                     <local:ExtendedInvokeCommandAction
 6                     Command="{Binding MouseMoved}"
 7                     CommandParameter="{Binding ElementName=userControl}"/>
 8                 </i:EventTrigger>
 9             </i:Interaction.Triggers>
10         </Rectangle>
11 

  5、在ViewModel层处理事件,代码如下

 1 public class MainPageViewModel : INotifyPropertyChanged
 2     {
 3         public MainPageViewModel()
 4         {
 5             MouseMoved = new MainPageCommand(this); //initialize the Command
 6         }
 7 
 8         //gets the position of the mouse
 9         private void OnMouseMove(ExtendedCommandParameter commandParameter)
10         {
11             MouseEventArgs eventArgs;
12 
13             //cast the EventArgs to the type you expect, according to the event you handle
14             //f.e. MouseMove Event  gets you MouseEventArgs
15             //     Click Event gets you RoutedEventArgs
16             if (commandParameter.EventArgs.GetType() == typeof(MouseEventArgs))
17             {
18                 eventArgs = commandParameter.EventArgs as MouseEventArgs;
19                 if (commandParameter.Parameter != null)
20                 {
21                     var view = commandParameter.Parameter as UIElement;
22                     MousePosition = eventArgs.GetPosition(view).ToString();
23                 }
24             }
25         }
26 
27         public MainPageCommand MouseMoved { getset; }
28         private string _mousePosition;
29         public string MousePosition
30         {
31             get { return _mousePosition; }
32             set { _mousePosition = value; OnPropertyChanged("MousePosition"); }
33         }
34 
35         #region INotifyChanged Members
36 
37         public event PropertyChangedEventHandler PropertyChanged;
38         internal void OnPropertyChanged(string propertyName)
39         {
40             if (this.PropertyChanged != null)
41             {
42                 this.PropertyChanged(thisnew PropertyChangedEventArgs(propertyName));
43             }
44         }
45 
46         #endregion
47 
48         #region command class
49 
50         public class MainPageCommand : ICommand
51         {
52             public MainPageCommand(MainPageViewModel view)
53             {
54                 _view = view;
55             }
56 
57             private MainPageViewModel _view;
58 
59             #region ICommand Members
60 
61             public bool CanExecute(object parameter)
62             {
63                 return true;
64             }
65 
66             public event EventHandler CanExecuteChanged;
67 
68             public void Execute(object parameter)
69             {
70                 //call the method to handle the event
71                 _view.OnMouseMove(parameter as ExtendedCommandParameter);
72             }
73 
74             #endregion
75 
76         }
77     #endregion
78 
79     }

  如果需要,可以为每一个EventArgs建一个Behavior,只要把它绑定到Command上,然后Command代码中处理EventArgs就可以了

  代码下载

  另外还有一篇英文的文章,和这篇文章差不多,但是写的更好,而且程序写的也很好,如果有兴趣的话,也看一下。文章地址为http://blog.roboblob.com/2010/01/26/binding-ui-events-from-view-to-commands-in-viewmodel-in-silverlight-4/