2011-02-04 70 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>