2013-01-01 41 views
1

的一個ObservableCollection是否有約定?綁定列表框的ViewModels

在下面的XAML中,我創建了一個ListBox的按鈕。 ListBox綁定到我的ViewModel的可觀察集合。然後我想將按鈕的Command屬性綁定到一個ICommand。問題是,當我添加綁定時,我綁定了數據對象,而不是ViewModel。

難道我只是改變MyListOfDataObjects屬性爲的ViewModels的名單?如果是這樣,我在哪裏實例化這些新對象?我寧願使用依賴注入,因爲它們會有幾個依賴關係。我是否更改GetData lambda?

一般來說:這裏認爲什麼是好的做法?我無法找到任何這種情況的例子,但我認爲這很常見。

我使用MVVMLight框架,但我願意看任何其他框架。

<Window x:Class="KeyMaster.MainWindow" 
     DataContext="{Binding Main, Source={StaticResource Locator}}"> 

    <Window.Resources> 
     <ResourceDictionary> 
      <DataTemplate x:Key="MyDataTemplate"> 
       <Button Command="{Binding ButtonPressedCommand}" 
         CommandParameter="{Binding .}" 
         Content="{Binding Name}" /> 
      </DataTemplate> 
     </ResourceDictionary> 
    </Window.Resources> 

    <Grid x:Name="LayoutRoot"> 
     <ListBox ItemsSource="{Binding MyListOfDataObjects}" 
       ItemTemplate="{StaticResource MyDataTemplate}"> 
      <ItemsControl.ItemsPanel> 
       <ItemsPanelTemplate> 
        <StackPanel Orientation="Horizontal" 
           IsItemsHost="True" /> 
       </ItemsPanelTemplate> 
      </ItemsControl.ItemsPanel> 
     </ListBox> 
    </Grid> 
</Window> 

我使用標準MVVMLight視圖模型:

using GalaSoft.MvvmLight; 
using KeyMaster.Model; 
using System.Collections.ObjectModel; 

namespace KeyMaster.ViewModel 
{ 
    public class MainViewModel : ViewModelBase 
    { 
     private readonly IDataService _dataService; 
     private ObservableCollection<MyData> _myListOfDataObjects; 

     public MainViewModel(IDataService dataService) 
     { 
      _dataService = dataService; 
      _dataService.GetData(
       (item, error) => 
       { 
        if (error != null) 
        { 
         return; 
        } 

        MyListOfDataObjects = new ObservableCollection<MyData>(item); 
       }); 
     } 

     public ObservableCollection<MyData> MyListOfDataObjects 
     { 
      get { return _myListOfDataObjects; } 
      set 
      { 
       if (_myListOfDataObjects == value) return; 

       _myListOfDataObjects = value; 
       RaisePropertyChanged(() => MyListOfDataObjects); 
      } 
     } 
    } 
} 

感謝。

+0

你是什麼意思*「我綁定數據對象,而不是ViewModel」*? – Blachshma

+0

@Blachshma我的意思是按下按鈕時調用的ButtonPressedCommand將是MyData類中定義的ButtonPressedCommand,而不是MainViewModel類中定義的。 – Josh

回答

0

在MVVM,存在的原始數據(也被稱爲模型)和視圖模型之間的明確分工。 ViewModel負責解析數據,甚至在將其傳遞給View之前,將其修改爲任何想要的形式。

一個簡單的例子是將Model作爲XML並使ViewModel解析它,從每個元素中只取一個特定的屬性(例如「Name」)並將它們添加到列表中。只有該列表將顯示在視圖中。

這麼說,我想你可以看到我要去哪裏 - 命令應該是在視圖模型在模型中。正如你自己所說的那樣,你應該儘可能多地從虛擬機和模型中取出UI邏輯。

如果您有特定的命令對特定類型的數據執行某些特定的操作,則可以將其更改爲「常規」類型的ViewModel,您可以使用CanExectue僅在特定情況下允許使用此命令。但是,該命令應該位於ViewModel中。

在您的具體情況,我沒有看到在視圖模型具有命令的問題,並提出時,它會做什麼,你需要在你的數據。你不需要ViewModel的列表,你只需要一個。

0

我會說它會取決於你想要的按鈕的功能。如果它始終與MyData對象相關,那麼(如果可能的話)將命令放在MyData對象中會不合適? (ps。我不會僅僅因爲你添加一個命令屬性給你的MyData對象ViewModels,因爲它們沒有與視圖關聯)

或者,如果你想在虛擬機中的命令,那麼你可以嘗試使用窗口的datacontext綁定命令。即類似的東西;

<Button Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.ButtonPressedCommand}" 
        CommandParameter="{Binding .}" 
        Content="{Binding Name}" /> 

儘管我過去遇到過麻煩,並且隨着將命令添加到單個對象中去了。

+0

這將命令綁定到MainWindow類,而不是MainWindowViewModel。更改路徑到DataContext.ButtonPressedCommand}修復了這個問題。 – Josh

+0

我已經考慮過這一點了,也許這更像是我在MVVM中表現出我的天真的一個實例,但我認爲其中的一個目標是保持數據對象中的UI邏輯儘可能多。爲此,我在一個由應用程序的其他部分使用的獨立項目中定義了數據類。一旦我添加命令到這個類,那麼我需要添加一個對WPF項目的引用。由於數據層也被Web服務使用,這看起來不自然。 – Josh

+0

@Josh謝謝你指出更正。我同意你的意見。如果它是一個只在一個視圖中使用的命令,那麼將它放入對象中並不會很好。我想如果你綁定到MainWindowViewModel,你將會在那裏有一個方法,它包含你的集合中所有項目的switch語句,這也不是我們想要的。也許你可以專門爲那個繼承MyData對象的集合創建一個新的對象 - 當你提到一個ViewModel列表時,你所指的是什麼? – Steve