Контекстное меню DataGrid. Получить значение

246
14 сентября 2017, 14:34

Решил уйти с winform и сразу же упёрся в проблему.

DataGrid'у добавил контекстное меню и не могу никак получить значение ячейки строки, в которой это меню было вызвано.

В winform'ах я делал так:

        var point = dataGridView1.PointToClient(contextMenuStrip1.Bounds.Location);
        var info = dataGridView1.HitTest(point.X, point.Y);
        string reader = dataGridView1[0, info.RowIndex].Value.ToString();

В WPF что-то не могу понять как это сделать.

Контекстное меню в дизайнере:

 <DataGrid x:Name="DataDevices" HorizontalAlignment="Left" Margin="0,50,0,0" VerticalAlignment="Top" Height="285" Width="270">
        <DataGrid.ContextMenu>
            <ContextMenu>
                <MenuItem Header="Звуковой сигнал" Click="Sound" />
                <MenuItem Header="Сигнал светодиода" Click="Blink" />
            </ContextMenu>
        </DataGrid.ContextMenu>
    </DataGrid>
Answer 1

Я расскажу как делать через команды.

Добавьте себе такой класс:

class DelegateCommand : ICommand
{
    protected readonly Predicate<object> _canExecute;
    protected readonly Action<object> _execute;
    public event EventHandler CanExecuteChanged;
    public DelegateCommand(Action<object> execute) : this(execute, _ => true) { }
    public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
    {
        _execute = execute ?? throw new ArgumentNullException(nameof(execute));
        _canExecute = canExecute ?? throw new ArgumentNullException(nameof(canExecute));
    }
    public bool CanExecute(object parameter) => _canExecute(parameter);
    public void Execute(object parameter) => _execute(parameter);
    public void RaiseCanExecuteChanged()
        => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}

Он представляет собой простую реализацию команды WPF.

Теперь для каждого пункта меню заведите команду, например:

public ICommand BeepCommand { get; }

В конструкторе VM (если вы используете MVVM) или своего окна создаете команду:

BeepCommand = new DelegateCommand(o => Beep((Item)o));

Здесь Item - это тип ваших элементов, которые вы выводите в DataGrid, далее сам метод, который будет вызываться по команде:

void Beep(Item item)
{
    ...
}

Также, если вы не используете подход MVVM, задайте окну контекст в конструкторе, например:

DataContext = this;

Теперь в разметке, добавим меню в ресурсы:

<Window.Resources>
    <ContextMenu x:Key="conMenu">
        <MenuItem Header="Звуковой сигнал"/>
        <MenuItem Header="Сигнал светодиода"/>
    </ContextMenu>
</Window.Resources>

разметка DataGrid:

<DataGrid ItemsSource="{Binding Items}">
    <DataGrid.RowStyle>
        <Style TargetType="DataGridRow">
            <Setter Property="ContextMenu" Value="{DynamicResource conMenu}"/>
        </Style>
    </DataGrid.RowStyle>
</DataGrid>

Теперь контекстное меню привязано к конкретной строке грида.

Привяжем теперь команды к пунктам меню.

Так как пункт меню помещен в DataGrid (который является ItemsControl'ом), то контекстом этого пункта является сам элемент, поэтому мы его легко можем передать в параметре CommandParameter="{Binding}", но сама команда определена в контексте окна, поэтому к ней придется идти через RelativeSource FindAncestor, в итоге получается вот что:

<MenuItem Header="Звуковой сигнал"
          Command="{Binding DataContext.BeepCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
          CommandParameter="{Binding}"/>

Всё, аналогично для остальных команд.

READ ALSO
Как передвигать окно не имея краев?

Как передвигать окно не имея краев?

При работе с winforms, возникла такая проблема: Надо передвигать окно с помощью мыши, у которого нет границ (FormBorderStyle = None) Как делать так чтобы...

181
Как телеграм боту получить доступ к сообщениям?

Как телеграм боту получить доступ к сообщениям?

Как телеграмм боту получить доступ к сообщениям пользователя и делать рассылку? Смысл- имеется несколько каналов и нужно, как только в каком-то...

360
VS 2017. Повторный build проекта

VS 2017. Повторный build проекта

После полного build solution, повторный build один проект пересобираетИз за чего такое может быть?

330