Используя MVVM, как передать SelectedItems XamDataGrid в качестве параметра в Команду, созданную ContextMenu? - PullRequest
5 голосов
/ 09 июня 2010

Я пытаюсь передать элемент в XamDataGrid, для которого я делаю щелчок правой кнопкой мыши, чтобы открыть ContextMenu, которое вызывает команду в моей ViewModel. Каким-то образом метод, вызываемый Командой, недоступен в режиме отладки.

Это разрезанный из вида

<ig:XamDataGrid DataSource="{Binding DrdResults}" Height="700" Width="600">
  <ig:XamDataGrid.ContextMenu>
    <ContextMenu DataContext="{Binding RelativeSource={RelativeSource Mode=Self},
                               Path=PlacementTarget.DataContext}"
                 AllowDrop="True" Name="cmAudit">
      <MenuItem Header="View History" 
                Command="{Binding ViewTradeHistory}"
                CommandParameter="{Binding Path=SelectedItems}">
      </MenuItem>
    </ContextMenu>
  </ig:XamDataGrid.ContextMenu>
  <ig:XamDataGrid.FieldSettings>
    <ig:FieldSettings AllowFixing="NearOrFar"
                      AllowEdit="False" 
                      Width="auto" Height="auto"  />
  </ig:XamDataGrid.FieldSettings>
</ig:XamDataGrid>

Мой код в соответствующей ViewModel для этого представления выглядит следующим образом.

public WPF.ICommand ViewTradeHistory
{
  get
  {
    if (_viewTradeHistory == null)
    {
      _viewTradeHistory = new DelegateCommand(
      (object SelectedItems) =>
      {
        this.OpenTradeHistory(SelectedItems); 
      });
    }
    return _viewTradeHistory;
  }
}

И, наконец, фактический метод, вызываемый Командой, выглядит следующим образом:

private void OpenTradeHistory(object records)
{
  DataPresenterBase.SelectedItemHolder auditRecords
    = (DataPresenterBase.SelectedItemHolder)records;
  // Do something with the auditRecords now.
}

Я не уверен, что я делаю здесь неправильно. Буду очень признателен за любую помощь.

Спасибо, Shravan

Ответы [ 4 ]

14 голосов
/ 18 октября 2012

Я работал над улучшением ответа Дамиана (который не совсем работал).

Вот мое решение:

Сначала Поведение:

public class DataGridExtender : Behavior<XamDataGrid>
{
    public readonly static DependencyProperty SelectedDataItemsProperty
        = DependencyProperty.Register(
            "SelectedDataItems",
            typeof(ICollection<object>),
            typeof(DataGridExtender),
            new PropertyMetadata());

    public ICollection<object> SelectedDataItems
    {
        get { return (ICollection<object>)GetValue(SelectedDataItemsProperty); }
        set { SetValue(SelectedDataItemsProperty, value); }
    }

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.SelectedItemsChanged += AssociatedObjectOnSelectedItemsChanged;
        AssociatedObjectOnSelectedItemsChanged(AssociatedObject, null);
    }

    protected override void OnDetaching()
    {
        AssociatedObject.SelectedItemsChanged -= AssociatedObjectOnSelectedItemsChanged;
        base.OnDetaching();
    }

    private void AssociatedObjectOnSelectedItemsChanged(object sender, Infragistics.Windows.DataPresenter.Events.SelectedItemsChangedEventArgs e)
    {
        if (SelectedDataItems != null)
        {
            SelectedDataItems.Clear();
            foreach (var selectedDataItem in GetSelectedDataItems())
            {
                SelectedDataItems.Add(selectedDataItem);
            }
        }
    }

    private IEnumerable<object> GetSelectedDataItems()
    {
        var selectedItems = from rec in AssociatedObject.SelectedItems.Records.OfType<DataRecord>() select rec.DataItem;
        return selectedItems.ToList().AsReadOnly();
    }
}

А затем его использование:

<igDP:XamDataGrid>
[...]

<i:Interaction.Behaviors>
    <Behaviours:DataGridExtender SelectedDataItems="{Binding SelectedDataItems, Mode=TwoWay}"></Behaviours:DataGridExtender>
</i:Interaction.Behaviors>

[...]

<igDP:XamDataGrid.FieldLayoutSettings>
    [...]
</igDP:XamDataGrid.FieldLayoutSettings>

<igDP:XamDataGrid.FieldLayouts>
    <igDP:FieldLayout>
        [...]
    </igDP:FieldLayout>
</igDP:XamDataGrid.FieldLayouts>

Конечно, вам нужно иметь "SelectedDataItems" в вашей модели представления.

Редактировать: Свойство SelectedDataItems в модели представления должно сначала вызываться как пустая коллекция, иначе оно не будет работать.

6 голосов
/ 13 января 2011

Для одного элемента Infragistics была достаточно любезна, чтобы добавить привязываемый объект DependencyProperty под названием «ActiveDataItem», который является «выбранным» элементом, если таковой имеется. Он даже работает в двух направлениях, то есть вы можете сбросить выделение из вашей ViewModel.

К сожалению, в AFAIK нет аналога для множественного выбора. Вам придется реализовать это самостоятельно, перебирая выбранные записи, проверять, являются ли они записями данных, получать записи, данные и т. Д. ...

2 голосов
/ 16 мая 2011

Для привязки к выбранным элементам я решил создать поведение с помощью System.Interactivity:

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Interactivity;
using Infragistics.Windows.DataPresenter;

namespace Sample {
    public class DataGridExtender : Behavior<XamDataGrid> {
        public readonly static DependencyProperty SelectedDataItemsProperty
            = DependencyProperty.Register(
                "SelectedDataItems"
                , typeof(ICollection<object>)
                , typeof(OzDataGridExtender)
                , new PropertyMetadata(null));

        public ICollection<object> SelectedDataItems {
            get { return (ICollection<object>)GetValue(SelectedDataItemsProperty); }
            set { SetValue(SelectedDataItemsProperty, value); }
        }

        protected override void OnAttached() {
            base.OnAttached();
            AssociatedObject.SelectedItemsChanged += AssociatedObjectOnSelectedItemsChanged;
            AssociatedObjectOnSelectedItemsChanged(AssociatedObject, null);
        }

        protected override void OnDetaching() {
            AssociatedObject.SelectedItemsChanged -= AssociatedObjectOnSelectedItemsChanged;
            base.OnDetaching();
        }

        private void AssociatedObjectOnSelectedItemsChanged(object sender, Infragistics.Windows.DataPresenter.Events.SelectedItemsChangedEventArgs e) {
            SelectedDataItems = GetSelectedDataItems();
            //AssociatedObject.SetValue(SelectedDataItemsPropertyKey, SelectedDataItems);
        }

        private ICollection<object> GetSelectedDataItems() {
            var selectedItems = from rec in AssociatedObject.SelectedItems.Records.OfType<DataRecord>()
                                select rec.DataItem;
            return selectedItems.ToList().AsReadOnly();
        }
    }
}

В некоторых случаях, по вашему мнению, было бы что-то вроде следующего (для краткости я пропустил отображения пространства имен):

Теперь ваша проблема с привязкой команды в контекстном меню, это что-то еще ... Я еще раз вернусь к этому

2 голосов
/ 09 июня 2010

Попробуйте связать SelectedItem вашей DataGrid со свойством в вашей модели представления.

Затем вы можете получить доступ к этому свойству в вашем методе OpenTradeHistory().

...