2016-02-26 38 views
1

我試圖執行基於列表視圖項目數據的方法。除此之外,如果ListView項的「CanExecute」方法返回true,則只應啓用觸發該命令的按鈕。使用棱鏡庫將ListView項目傳遞給命令

我的ViewModel中包含「MyCommand」和「CanExecute」兩種方法。 不幸的是,我不確定如何正確地將項目信息傳遞給兩種方法以符合PRISM 6框架。

所以我的第一種方法是做如下所示:

型號

public class MyModel 
{ 
    public string Name { get; set; } 
    public string Version { get; set; } 
    public int Identifier { get; set; } 
} 

視圖模型

public class MyViewModel : BindableBase 
{ 

    private ObservableCollection<MyModel> _models = new ObservableCollection<MyModel>(); 
    public ObservableCollection<MyModel> Models 
    { 
     get { return _models; } 
     set { SetProperty(ref _models, value); } 
    } 

    public DelegateCommand VerifyCommand { get; set; } 


    public MyViewModel() 
    { 
     //Add test data 
     for (int i = 0; i < 5; i++) 
     { 
      MyModel model = new MyModel(); 
      model.Name = "Random Text"; 
      model.Version = "Random Text"; 
      model.Identifier = i; 

      Models.Add(model); 
     } 

     //Doesn't work, because I don't reference to "Models" 
     //How to do that? 
     VerifyCommand = new DelegateCommand(DoCommand, CanExecute).ObservesProperty<string>(() => Name).ObservesProperty<string>(() => Version); 
    } 

    private bool CanExecute() 
    { 
     //Obviously this doesn't work, because "Version" and "Name" 
     //don't belong to the selected "Models" item of the listview 

     //What is the "bridge", to know which item of Models was clicked (button) 
     return !String.IsNullOrWhiteSpace(Version) && !String.IsNullOrWhiteSpace(Name); 
    } 

    private void DoCommand() 
    { 
     //Do something special 
    } 
} 

查看

<ListView ItemsSource="{Binding Models}"> 
    <ListView.ItemTemplate> 
     <DataTemplate> 
      <Grid Height="Auto" Margin="0,0,0,10"> 
       <Grid.RowDefinitions> 
        <RowDefinition/> 
        <RowDefinition/> 
        <RowDefinition/> 
       </Grid.RowDefinitions> 
       <TextBox Grid.Row="0" Tag="VERSION" Text="{Binding Version, UpdateSourceTrigger=PropertyChanged}" /> 
       <TextBox Grid.Row="1" Tag="NAME" Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" /> 
       <Button Command="{Binding ElementName=root, Path=DataContext.VerifyCommand}" Content="Verify" Grid.Row="2"> 
      </Grid> 
     </DataTemplate> 
    </ListView.ItemTemplate> 
</ListView> 

查看和視圖模型做之間的聯繫通過:

prism:ViewModelLocator.AutoWireViewModel="True" 
在我看來

(這工作)。

總之: PRISM是如何工作的只有在CanExecute爲true的情況下才啓用項目按鈕,並且執行「DoCommand」方法並將項目信息傳遞給該按鈕(按鈕的根元素 - >在這種情況下,ListViewItem的(爲MyModel)

任何幫助,將不勝感激

+2

您應該爲您的模型查看模型 - 然後執行命令。即該視圖具有視圖模型,並且該視圖模型公開了「ModelViewModel」的列表。順便說一句 - 「模型」屬性可能不需要setter,除非你打算從外部設置它(通過數據綁定)... – Haukinger

+0

你選擇了一個你想驗證的項目還是可以從列表中選擇多個項目? – Tseng

回答

3

簡短的回答:在該項目的視圖模型把命令

龍答:

小時。。。這就是我在上面評論中的意思的一個例子。如果你真的需要一個可觀察的模型集合和一個可觀察的視圖模型集合,爲自己準備了許多無聊的雙向同步代碼,我已經省略了這些集合的可觀察性...

型號:

internal class ItemModel 
{ 
    public string Name { get; set; } 
    public string Version { get; set; } 
    public int Identifier { get; set; } 
} 

的ViewModels(一個項目的集合,也就是你的MyViewModel,以及一個用於項目):

internal class MyCollectionViewModel : BindableBase 
{ 
    private readonly List<ItemModel> _models = new List<ItemModel>(); 

    public MyCollectionViewModel() 
    { 
     //Add test data 
     for (var i = 0; i < 5; i++) 
      _models.Add(new ItemModel 
      { 
       // to prove that CanExecute is actually evaluated... 
       Name = i == 3 ? "Random Text" : string.Empty, 
       Version = "Random Text", 
       Identifier = i 
      }); 
    } 

    public IReadOnlyCollection<ItemViewModel> TheCollection => _models.Select(x => new ItemViewModel(x)).ToList(); 
} 

internal class ItemViewModel : BindableBase 
{ 
    public ItemViewModel(ItemModel item) 
    { 
     _item = item; 
     VerifyCommand = new DelegateCommand(() => 
              { 
               /* Do something */ 
              },() => !string.IsNullOrWhiteSpace(Version) && !string.IsNullOrWhiteSpace(Name)); 
    } 

    public string Name => _item.Name; 
    public string Version => _item.Version; 
    public int Identifier => _item.Identifier; 

    public DelegateCommand VerifyCommand 
    { 
     get; 
    } 

    private readonly ItemModel _item; 
} 

查看:

<ListView ItemsSource="{Binding TheCollection}"> 
    <ListView.ItemTemplate> 
     <DataTemplate> 
      <Grid Height="Auto" Margin="0,0,0,10"> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition/> 
        <ColumnDefinition/> 
        <ColumnDefinition/> 
       </Grid.ColumnDefinitions> 
       <TextBox Grid.Column="0" Text="{Binding Version, Mode=OneWay}" /> 
       <TextBox Grid.Column="1" Text="{Binding Name, Mode=OneWay}" /> 
       <Button Grid.Column="2" Command="{Binding VerifyCommand}" Content="Verify"/> 
      </Grid> 
     </DataTemplate> 
    </ListView.ItemTemplate> 
</ListView> 
+0

感謝Haukinger。這似乎是一個很好的方法。 – user1011394