Saruman Saruman - 8 months ago 80
C# Question

How to bind a WPF ListView with contextMenu to viewModel

I'm trying to bind a listview to

List<OrderPaymentVm> OrderPayments

with a right click contextmenu to get the

I have the following property in my forms view model

public List<OrderPaymentVm> OrderPayments
return _orderPayments;

private set
_orderPayments = value;
RaisePropertyChanged(() => OrderPayments);

The ViewModel

public class OrderPaymentVm : ViewModelBase

private RelayCommand _copyPaymentTransactionId;
public DateTime PaymentTime { get; set; }
public PaymentType PaymentType { get; set; }
public string Explanation { get; set; }
public string PaymentTransactionId { get; set; }
public decimal Amount { get; set; }
public RelayCommand CopyPaymentTransactionId
get { return _copyPaymentTransactionId ?? (_copyPaymentTransactionId = new RelayCommand(ExecuteCopyPaymentTransactionId)); }

private void ExecuteCopyPaymentTransactionId()
Clipboard.SetText(string.IsNullOrWhiteSpace(PaymentTransactionId) ? string.Empty : PaymentTransactionId);


I have the following xaml

<ListView Grid.Row="1" ItemsSource="{Binding OrderPayments}" HorizontalAlignment="Stretch" Margin="0,0,0,1">
<MenuItem Header="Copy Transaction Id"
Command="{Binding CopyPaymentTransactionId}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.SelectedItem}" />
<GridViewColumn HeaderContainerStyle="{StaticResource HeaderLeftAlign}" Header="Transaction Id" Width="150" DisplayMemberBinding="{Binding PaymentTransactionId}" />
<GridViewColumn HeaderContainerStyle="{StaticResource HeaderLeftAlign}" Header="Time" Width="150" DisplayMemberBinding="{Binding PaymentTime}" />
<GridViewColumn HeaderContainerStyle="{StaticResource HeaderLeftAlign}" Header="Payment Type" Width="100" DisplayMemberBinding="{Binding PaymentType}" />
<GridViewColumn HeaderContainerStyle="{StaticResource HeaderLeftAlign}" Header="Amount" Width="80" DisplayMemberBinding="{Binding Amount, StringFormat='{}{0:C}'}" />
<GridViewColumn HeaderContainerStyle="{StaticResource HeaderLeftAlign}" Header="Explanation" Width="280" DisplayMemberBinding="{Binding Explanation}" />

Problem 1
the xaml designer says there is a problem with the GridViewColumn bindings, it underlines them and says it cannot resolve property, however it compiles and works fine

Problem 2
The ConextMenu Command is not hitting the viewmodel command
RelayCommand CopyPaymentTransactionId

Im sure these are simple issues however im spinning my wheels, does any one have any suggestions?


Answer Source

here is solution for the 2nd problem. as the context menu is hosted in a popup, which does not inherit the data context from it's parent as it is a separate root element. so you may not simply bind to the parent element's view model.

here is example to bind the command in a context menu

Command="{Binding PlacementTarget.SelectedItem.CopyPaymentTransactionId,
                  RelativeSource={RelativeSource AncestorType=ContextMenu}}"

similar to command parameter, you need to specify the source for the command binding.

to simplify you may also write the same as

<MenuItem Header="Copy Transaction Id"
          DataContext="{Binding PlacementTarget.SelectedItem, 
                                RelativeSource={RelativeSource AncestorType=ContextMenu}}"
          Command="{Binding CopyPaymentTransactionId}"
          CommandParameter="{Binding}" />