So I have a context menu for each individual listview item and the listview is bound to a user list. The context menu has a sub-menu that is bound to an observable collection of user statuses. I want to be able to pass the user id from the list view AND the new status ID from the context menu to my update command parameter. I just looked in to MultiBindings and believe this may be a good, long term solution that I can use elsewhere. Here is some code:
ListView from User View:
<ListView Background="Transparent" ItemsSource="{Binding UserList}" SelectionMode="Single">
<ListView.Resources>
<ContextMenu x:Key="Menu" DataContext="{Binding Path=PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
<MenuItem Name="UserID" Header="{Binding UserID}"/>
<Separator></Separator>
<MenuItem Header="Status" ItemsSource="{Binding DataContext.UserStatus, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"
DisplayMemberPath="Name" Name="StatusID">
<MenuItem.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Command" Value="{Binding DataContext.UpdateDriverStatus, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" />
<Setter Property="CommandParameter" Value="{Binding}" />
</Style>
</MenuItem.ItemContainerStyle>
<MenuItem.CommandParameter>
<MultiBinding Converter="{StaticResource MultiBindConverter}">
<Binding ElementName="DriverID"></Binding>
<Binding ElementName="StatusID"></Binding>
</MultiBinding>
</MenuItem.CommandParameter> </MenuItem>
</ContextMenu>
</ListView.Resources>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="ContextMenu" Value="{StaticResource Menu}" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<ItemContainerTemplate>
<TextBlock Text="{Binding UserName}" >
</TextBlock>
</ItemContainerTemplate>
</ListView.ItemTemplate>
</ListView>
User VM:
public class UsersPanelVM : ViewModelBase, INotifyPropertyChanged
{
public ObservableCollection<UserPanelItem> UserList { get; set; }
public ObservableCollection<UserStatusList> UserStatus { get; set; }
private readonly IUserService _userService;
public IUserService UserService { get { return this._userService; } }
public UsersPanelVM(IUserService userService)
{
this._userService = userService;
var model = this.UserService.GetUsers();
this.UserList = model.Users;
var statusmodel = this.UserService.GetUserStatus();
this.UserStatus = statusmodel.UserStatus;
this.UpdateUserStatus = new RelayCommand<UserStatusList>((s) => UpdateStatus(1,s));
}
//The 1, above, is hard coded to test the method call, but ideally that should be the selected UserID
private void UpdateStatus(int ID, UserStatusList s)
{
}
public RelayCommand<UserStatusList> UpdateUserStatus { get; private set; }
}
I'm pretty sure I am 100% lost at this point.
This is not necessary as i already mentioned in your other question because you have all the information except the new status in your object model.
Move the command and the UpdateStatus
method into the UserPanelItem
's class, which also should hold your ID, then you just need to change the command to:
new RelayCommand(param => UpdateStatus(ID, (UserStatusList)param))
If you really want to do it this way: You again set the CommandParameter
of the parent MenuItem
whose Command will never even be used, move it to the CommandParameter
-Setter
's Value
in the container style, i.e.
<Setter Property="CommandParameter">
<Setter.Value>
<MultiBinding ...>
....