views:

196

answers:

1

I've got a ItemsControl (to be replaced by listbox) which has it's ItemsSource bound to an ObservableCollection<User> which is located in the view model.

The View Model contains some DelegateCommand<T> delegates for handling commands (for instance UpdateUserCommand and RemoveUserCommand). All works fine if the buttons linked to those commands are placed outside of the DataTemplate of the control which is presenting the items.

<ItemsControl ItemsSource="{Binding Users, Mode=TwoWay}" HorizontalContentAlignment="Stretch"> <ItemsControl.ItemTemplate> <DataTemplate> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="0.2*"/> <ColumnDefinition Width="0.2*"/> <ColumnDefinition Width="0.2*"/> <ColumnDefinition Width="0.2*"/> <ColumnDefinition Width="0.2*"/> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Text="{Binding UserName}"/> <PasswordBox Grid.Column="1" Password="{Binding UserPass}"/> <TextBox Grid.Column="2" Text="{Binding UserTypeId}"/> <Button Grid.Column="3" Content="Update" cal:Click.Command="{Binding UpdateUserCommand}" cal:Click.CommandParameter="{Binding}"/> <Button Grid.Column="4" Content="Remove" cal:Click.Command="{Binding RemoveUserCommand}" cal:Click.CommandParameter="{Binding}"/> </Grid>
</DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>

What I'm trying to achieve, is : Have each row - generated by the ListView/ItemsControl - contain buttons to manage the item represented that particular row.


During the runtime, the VS's output panel generated the following messages for each listbox element

System.Windows.Data Error: BindingExpression path error: 'UpdateUserCommand' property not found on 'ModuleAdmin.Services.User' 'ModuleAdmin.Services.User' (HashCode=35912612). BindingExpression: Path='UpdateUserCommand' DataItem='ModuleAdmin.Services.User' (HashCode=35912612); target element is 'System.Windows.Controls.Button' (Name=''); target property is 'Command' (type 'System.Windows.Input.ICommand')..
System.Windows.Data Error: BindingExpression path error: 'RemoveUserCommand' property not found on 'ModuleAdmin.Services.User' 'ModuleAdmin.Services.User' (HashCode=35912612). BindingExpression: Path='RemoveUserCommand' DataItem='ModuleAdmin.Services.User' (HashCode=35912612); target element is 'System.Windows.Controls.Button' (Name=''); target property is 'Command' (type 'System.Windows.Input.ICommand')..

Which would imply that there are binding errors present.

Is there any way to make this right? or is this not the way?

+2  A: 

The DataTemplate gets its DataContext explicitly set to the item the template is representing. That is to say, your DataTemplate's DataContext would be a User object, not the ViewModel that contains the ObservableCollection. The way your commands are being bound, it's expecting to find the commands on the User object.

You can explicitly set the binding source or you can override the data context.

<ItemsControl HorizontalContentAlignment="Stretch" ItemsSource="{Binding Users, Mode=TwoWay}">
 <ItemsControl.ItemTemplate>
    <DataTemplate>
    ...
      <Button
         Grid.Column="3"
         cal:Click.Command="{Binding UpdateUserCommand, Source={StaticResource myVM}}"
         cal:Click.CommandParameter="{Binding}"
         Content="Update"/>
      <Button
         Grid.Column="4"
         cal:Click.Command="{Binding RemoveUserCommand, Source={StaticResource myVM}}"
         cal:Click.CommandParameter="{Binding}"
         Content="Remove"/>
    ...
    </DataTemplate>
 </ItemsControl.ItemTemplate>
</ItemsControl>
Josh Einstein
thanks, I couldn't figure this one out for the better part of the day
Maciek