2009-06-26 137 views
9

我目前正在將一個小的WPF項目轉換爲MVVM。在我的ItemsControl綁定的主窗口的ViewModel中有一個List<CustomObject>,並使用DataTemplate構建每個元素的UI。我的舊代碼在DataTemplate中使用了一個事件處理程序來處理點擊事件。我想使用某種命令綁定來消除我的代碼隱藏事件處理程序,但是我的ItemsControl中的項目的DataContext是模型對象,所以我目前無法綁定到ViewModel中的ICommand。WPF MVVM - 命令綁定在一個ItemsControl內

因此,我想有幾種方法可以解決這個問題,我不確定哪個是最「MVVM」的方式。我是否將ItemsControl.ItemsSource綁定到代表每個項目的新ViewModel類的集合?或者我使用UserControl而不是DataTemplate,然後我可以將每個UserControl綁定到它自己的ViewModel實例上來表示它?或者是否有某種綁定表達式可以用來引用窗口的DataContext以訪問綁定到ViewModel(因爲我鍵入這個,它聽起來很糟糕,所以我假設一個大的「否」理念)?

此外,我想要綁定我的命令是網格控件的LeftMouseButtonUp事件。 Grid沒有「命令」,所以我試圖使用InputBindings。我可以使用靜態命令(比如內置的ApplicationCommand之一),但我不能使用綁定表達式綁定到ViewModel屬性的ICommand實例,因爲MouseBinding.Command不是DependencyProperty。

對於MVVM中事件處理的主題我感到很困惑,所以任何和所有的信息都是值得讚賞的。

回答

4

Josh Smith在MSDN here上寫了一篇很好的文章,談論命令綁定。

在你的情況下,它歸結爲:

  • 你不會消除所有你的代碼隱藏,但它可能會尋找不同的
  • 你CustomObjects可能要有VM墊片類,或者是VM自己利用他描述的RelayCommand體系結構。

HTH。

19

是否將ItemsControl.ItemsSource綁定到代表每個項目的新ViewModel類的集合?

是否創建一個CustomObjectViewModel來託管該命令或將該命令放置在具有該列表的同一個ViewModel中真的取決於該動作發生的功能。它是屬於CustomObject的東西嗎?還是它屬於你當前的ViewModel?

或者是有一些種類的結合表達我可以用它來指代回DataContext的窗口有機會獲得綁定到視圖模型(我鍵入此,它只是聽起來很糟糕,所以我假設對這個想法大「不」)?

這並不像聽起來那麼糟糕。您並不真的需要窗口的DataContext,只是從切換到單個項目之前的DataContext。所以,如果您的命令是在承載CustomObjects的列表相同視圖模型,你可以使用以下兩種方法之一綁定到它從內CustomObject的DataTemplate中的一個:

{Binding ElementName=uiCustomObjectsItemsControl, Path=DataContext.MyCommand} 
{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemsControl}}, Path=DataContext.MyCommand} 

另外,我要綁定什麼我的命令 爲網格控件的 的LeftMouseButtonUp事件。沒有「命令」 一個網格,所以我試圖使用 InputBindings。

爲此,我會使用類似Attached Command Behaviors這將允許您將ICommand附加到任何事件。

1

您可以嘗試在您的模型中保留您的命令。

public class MyModel 
{ 
    public MyModel() 
    { 
     MyCommand = new DelegateCommand(MyCommandExecute); 
    } 

    public ICommand MyCommandCommand { get; set; } 

    private void MyCommandExecute() 
    { 
    } 
} 

然後,你必須爲你的視圖模型作爲您的項目列表中的ObservableList,他們

public class MyViewModel 
{ 
    public MyViewModel() 
    { 
     MyStarterCommand = new DelegateCommand(MyCommandExecute); 

     if (!IsDesignTime)//(bool)DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty, typeof(DependencyObject)).Metadata.DefaultValue; 
      MyCommand.Execute(null); 
    } 

    private ObservableCollection<MyModel> list; 
    private ICommand MyStarterCommand { get; set; } 

    public ObservableCollection<MyModel> List 
    { 
     get { return list; } 
     set 
     { 
      list = value; 
      RaisePropertyChanged(() => List); 
     } 
    } 

    private void MyStarterCommandExecute() 
    { 
     List = new ObservableCollection<MyModel>(); 

     //Fill the list here 
     List.Add(new MyModel()); 
    } 
} 

然後在XAML,你必須說;

<ItemsControl ItemsSource="{Binding List}"> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <Button Content="MyButton" Command="{Binding MyCommand}" /> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl>