2016-02-26 37 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