У меня есть приложение WPF, в котором Window имеет отношение master / child.Когда пользователь выбирает Покупателя из ListView, DataGrid связывается со связанными предметами, которые они приобрели.В GridView слева есть кнопка, где можно произвести оплату за этот отдельный элемент.Однако я хочу отключить / включить кнопку в зависимости от состояния элемента, независимо от того, связан ли с ним существующий платеж.Использование Galasoft MVVM Light, RelayCommand во всем приложении.У меня кнопка Pay работает, но ТОЛЬКО при нажатии (выбранная строка).Это прекрасно работает, когда привязан к команде следующим образом:
<DataGrid ..
ItemsSource="{Binding Items}"
SelectedItem="{Binding SelectedItem}"
IsSynchronizedWithCurrentItem="True"
.. >
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button ...
Command="{Binding Path=DataContext.PayItemCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"
CommandParameter="{Binding SelectedItem, Mode=OneWay, ElementName=itemsPurchasedGrid}"
>Pay</Button>
...
// in ctor
PayItemCommand = new RelayCommand<Item>(PayItem, IsItemUnPaid);
// in body
private void PayItem(Item item)
{
PaymentMode = PaymentMode.Item;
Messenger.Default.Send<BuyerViewModel>(this, "LaunchPayWindow");
}
// CanExecute impl
private bool IsItemUnPaid(Item item)
{
// code to determine if item is already paid
}
Итак, когда я нажимаю кнопку, он правильно передает SelectedItem делегату RelayCommand.Однако реализация CanExecute: IsItemUnPaid (Item item) никогда не получает элемент, потому что он (еще) не выбран.Я попытался: IsSynchronizedWithCurrentItem = "True", который всегда пропускает первый элемент, но не любые другие.Есть ли способ получить дескриптор элемента, когда он привязан к DataGrid, чтобы отключить / включить его?Я уверен, что во время связывания есть неприятные пути в коде, но есть ли способ MVVM проверить текущий элемент и переключить эту кнопку?Большое спасибо!
PS Я написал простой конвертер, который работает, но действительно ли это лучший способ?
public class PayItemConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (!(value is Item item))
return true;
// if you find any payments for this item...
var payments = (item.Payments != null && item.Payments.Any(p => p.ItemId.HasValue && p.ItemId.Value == item.Id))
? item.Payments.Where(p => p.ItemId.HasValue && p.ItemId.Value == item.Id).ToArray()
: null;
// if you find payments for this item, are the sum of the payments less than the total of the item TotalAmount, it is said to be unpaid
return (payments != null && payments.Length > 0)
? payments.Sum(p => p.Amount) < item.TotalAmount
: true;
}