2011-02-04 77 views
40

我正在做一些简单的应用程序的重构,以遵循MVVM和我的问题是如何将SelectionChanged事件移出我的代码后面到viewModel?我已经看过一些命令的绑定元素的例子,但并没有完全理解它。任何人都可以协助这一点。谢谢!WPF绑定UI事件ViewModel中的命令

任何人都可以使用下面的代码提供解决方案吗?非常感谢!

public partial class MyAppView : Window 
{ 
    public MyAppView() 
    { 
     InitializeComponent(); 

     this.DataContext = new MyAppViewModel(); 

     // Insert code required on object creation below this point. 
    } 

    private void contactsList_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) 
    { 
     //TODO: Add event handler implementation here.   
     //for each selected contact get the labels and put in collection 

     ObservableCollection<AggregatedLabelModel> contactListLabels = new ObservableCollection<AggregatedLabelModel>(); 

     foreach (ContactListModel contactList in contactsList.SelectedItems) 
     { 
      foreach (AggregatedLabelModel aggLabel in contactList.AggLabels) 
      { 
       contactListLabels.Add(aggLabel); 
      } 
     } 
     //aggregate the contactListLabels by name 
     ListCollectionView selectedLabelsView = new ListCollectionView(contactListLabels); 

     selectedLabelsView.GroupDescriptions.Add(new PropertyGroupDescription("Name")); 
     tagsList.ItemsSource = selectedLabelsView.Groups; 
    } 
} 

回答

83

你应该结合InvokeCommandAction使用EventTrigger从Windows.Interactivity命名空间。这里有一个例子:

<ListBox ...> 
    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="SelectionChanged"> 
      <i:InvokeCommandAction Command="{Binding SelectedItemChangedCommand}"/> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 
</ListBox> 

您可以通过Add reference > Assemblies > Extensions引用System.Windows.Interactivity

而完整的i命名空间是:xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

+0

感谢。我是编程的新手,所以原谅我 - 你能用我提供的代码举个例子吗? – Ben 2011-02-06 21:49:18

+1

您基本上需要在ViewModel中创建一个名为“SelectedItemChangedCommand”的命令属性。命令与事件类似,但命令不同于事件,只能有一个回调函数。检查文档:http://msdn.microsoft.com/en-us/library/ms752308.aspx – Brian 2011-02-13 01:55:08

+1

如果您没有Expression Blend,则需要SDK:http://www.microsoft.com/downloads/ en/details.aspx?FamilyID = D197F51A-DE07-4EDF-9CBA-1F1B4A22110D&displaylang = en – Murven 2011-02-14 04:06:34

0

正如@Cameron MacFarland所提到的,我只是简单地将双向绑定到viewModel上的一个属性。在属性设置器中,您可以执行任何您需要的逻辑,例如添加到联系人列表,具体取决于您的要求。

但是,我不一定会调用属性'SelectedItem',因为viewModel不应该知道视图图层以及它如何与它的属性进行交互。我会把它叫做CurrentContact或其他东西。

这显然是,除非你只是想创建命令作为练习练习等

7

重构这一点,你需要改变你的思想。您将不再处理“选择已更改”事件,而是将选定的项存储在您的视图模型中。然后,您将使用双向数据绑定,以便当用户选择一个项目时,您的视图模型会更新,并且当您更改所选项目时,您的视图会更新。

1

我会按照这个question

基本上您的视图模型上的答案将包含所有项目的列表,并选择项目列表。然后,您可以将行为附加到管理您所选项目列表的列表框中。

这样做意味着您在后面的代码中没有任何内容,并且xaml很容易遵循,行为也可以在应用程序的其他位置重新使用。

<ListBox ItemsSource="{Binding AllItems}" Demo:SelectedItems.Items="{Binding SelectedItems}" SelectionMode="Multiple" /> 
2
<ListBox SelectionChanged="{eb:EventBinding Command=SelectedItemChangedCommand, CommandParameter=$e}"> 

</ListBox> 

命令

{EB:EventBinding}(简单命名模式找到命令)

{EB:EventBinding命令=的CommandName}

CommandParameter

$ E(EventAgrs)

$本或$ this.Property

https://github.com/JonghoL/EventBindingMarkup

1

有时结合事件通过交互命令触发不工作,在需要时解决方案绑定自定义用户控件的事件。 在这种情况下,您可以使用自定义行为。

申报绑定行为,如:

public class PageChangedBehavior 
{ 
    #region Attached property 

    public static ICommand PageChangedCommand(DependencyObject obj) 
    { 
     return (ICommand)obj.GetValue(PageChangedCommandProperty); 
    } 
    public static void SetPageChangedCommand(DependencyObject obj, ICommand value) 
    { 
     obj.SetValue(PageChangedCommandProperty, value); 
    } 

    public static readonly DependencyProperty PageChangedCommandProperty = 
     DependencyProperty.RegisterAttached("PageChangedCommand", typeof(ICommand), typeof(PageChangedBehavior), 
      new PropertyMetadata(null, OnPageChanged)); 

    #endregion 

    #region Attached property handler 

    private static void OnPageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var control = d as PageControl; 
     if (control != null) 
     { 
      if (e.NewValue != null) 
      { 
       control.PageChanged += PageControl_PageChanged; 
      } 
      else 
      { 
       control.PageChanged -= PageControl_PageChanged; 
      } 
     } 
    } 

    static void PageControl_PageChanged(object sender, int page) 
    { 
     ICommand command = PageChangedCommand(sender as DependencyObject); 

     if (command != null) 
     { 
      command.Execute(page); 
     } 
    } 

    #endregion 

}

然后将它绑定到在XAML命令:

 <controls:PageControl 
      Grid.Row="2" 
      CurrentPage="{Binding Path=UsersSearchModel.Page,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
      PerPage="{Binding Path=UsersSearchModel.PageSize,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
      Count="{Binding Path=UsersSearchModel.SearchResults.TotalItemCount}" 
      behaviors:PageChangedBehavior.PageChangedCommand="{Binding PageChangedCommand}"> 
     </controls:PageControl>