WPF MVVM DataTemplate:使用来自父Viewmodel的数据注入模板ViewModel

时间:2013-03-22 11:46:42

标签: wpf mvvm view viewmodel datatemplate

我的父ViewModel中有一个ObservableCollection,我希望在父View中显示。所以我已经定义了一个子View和一个子ViewModel处理按钮点击。 如何将ObservableCollection中的每个项目都放到相应的子ViewModel中,而不会丢失我已设置的RelayCommands以进行按钮点击处理?

在我的父视图代码后面我唯一要做的就是将DataContext设置为适当的ViewModel:

DataContext = new ParentViewModel();

在我的父视图XAML中,我定义了一个ListBox来显示我的子视图的DataTemplate:

<ListBox
  ItemsSource="{Binding Path=Items}">
  <ListBox.ItemTemplate>
    <DataTemplate DataType="{x:Type vm:ChildViewModel}">
      <views:ChildView Width="auto" />
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

现在在我的ChildView中,我得到了几个显示绑定数据和按钮的TextBlocks,它们应该在ObservableCollection中指定的路径中执行文件:

<TextBlock
  Text="{Binding Path=Title}" />
...
<Button
  Content="Start exe"
  Tag="{Binding Path=ExePath}">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="Click">
      <i:InvokeCommandAction Command="{Binding Path=OnButtonClicked}" />
    </i:EventTrigger>
  </i:Interaction.Triggers>
</Button>

Child ViewModel保存RelayCommands以处理Button click事件:

private RelayCommand onButtonClicked;
public ICommand OnButtonClicked
{
  get
  {
    return onButtonClicked ??
      (onButtonClicked =
      new RelayCommand(ObeyOnButtonClicked, CanObeyOnButtonClicked));
  }
}
private void ObeyOnButtonClicked()
{
  ... //Path conversion
  Process.Start(pathToExe);
}
private bool CanObeyOnButtonClicked()
{
  return true;
}

现在,在我的孩子View的Code-Behind中,当我添加

DataContext = new SampleItemViewModel();

到构造函数,处理按钮单击,但TextBox都是空的。 删除此行时,TextBox会正确填充,但不会处理按钮单击。

如何让这两项功能都有效?

编辑:

ParentViewModel:

private ObservableCollection<Item> items;
public ObservableCollection<Item> Items
{
  get { return items; }
  set
  {
    items= value;
    OnPropertyChanged("Items");
  }
}

... //Filling the Collection in Constructor

ChildViewModel仅包含上面提到的按钮点击处理程序。

编辑:

我现在尝试了几件事,但我不知道如何将Command从ChildView绑定到我的ChildViewModel而不将我的ChildView的DataContext设置为我的ChildViewModel

1 个答案:

答案 0 :(得分:1)

您可以删除事件触发器,因为Button具有Command属性。

<TextBlock Text="{Binding Path=Title}" />
...
<Button
  Content="Start exe"
  Tag="{Binding Path=ExePath}"
  Command="{Binding Path=OnButtonClicked}"
>
</Button>

并设置DataContext:

<ListBox
  ItemsSource="{Binding Path=Items}">
  <ListBox.ItemTemplate>
    <DataTemplate DataType="{x:Type vm:ChildViewModel}">
      <views:ChildView Width="auto" DataContext="{Binding}" />
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>