2
votes

I have an ObservableCollection in my parent ViewModel which I want to display in the parent View. So I've defined a child View and a child ViewModel handling button clicks. How do I get each item from the ObservableCollection into the according child ViewModel without loosing my already setup RelayCommands for button click handling?

In my parent View Code-Behind the only thing I do is setting the DataContext to the appropiate ViewModel:

DataContext = new ParentViewModel();

In my parent View XAML I defined a ListBox to display a DataTemplate of my child View:

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

Now in my ChildView I got several TextBlocks displaying the Binding Data and Buttons which should execute a file in a path specified within the 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>

The Child ViewModel holds RelayCommands to handle the Button click event:

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;
}

Now, within my child View's Code-Behind, when I add

DataContext = new SampleItemViewModel();

to the Constructor, the Button click is handled but the TextBoxes are all empty. When i remove this line, the TextBoxes are filled correctly, but the Button Clicks are not handled.

How do I get both features working?

EDIT:

ParentViewModel:

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

... //Filling the Collection in Constructor

ChildViewModel contains just the above mentioned button click handlers.

EDIT:

I tried several things now but I don't know how to bind the Command from the ChildView to my ChildViewModel WITHOUT setting the DataContext of my ChildView to my ChildViewModel

1

1 Answers

1
votes

You can remove the Event Trigger, as Button has a Command property.

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

And set the DataContext :

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