Решил уйти с 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>
Я расскажу как делать через команды.
Добавьте себе такой класс:
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}"/>
Всё, аналогично для остальных команд.
Виртуальный выделенный сервер (VDS) становится отличным выбором
При работе с winforms, возникла такая проблема: Надо передвигать окно с помощью мыши, у которого нет границ (FormBorderStyle = None) Как делать так чтобы...
Как телеграмм боту получить доступ к сообщениям пользователя и делать рассылку? Смысл- имеется несколько каналов и нужно, как только в каком-то...
После полного build solution, повторный build один проект пересобираетИз за чего такое может быть?