У меня есть DataGrid, и я хотел бы переключить видимость отдельных столбцов DataGridTextColumns с помощью команд, отправленных из ContextMenu. Мне нужен какой-то способ связать определенный DataGridTextColumn или его параметр Visibility с командой ContextMenu MenuItem. Я могу установить отдельные переменные видимости в моей ViewModel и переключать их с помощью отдельных команд, по одной на каждую DataGridTextColumn, что работает отлично, но у меня много много DataGridTextColumns, и это кажется очень повторяющимся, беспорядочным и, вероятно, неправильным способом решения проблемы. .
Пример .xaml:
<FrameworkElement x:Name="dummyElement" Visibility="Collapsed"/>
<DataGrid ItemsSource="{Binding Shots}" SelectedItem="{Binding SelectedShot, Mode=TwoWay}" AutoGenerateColumns="False" HorizontalScrollBarVisibility="Auto" IsReadOnly="True" AreRowDetailsFrozen="True" HeadersVisibility="All" >
<DataGrid.Columns>
<DataGridTextColumn Visibility="{Binding DataContext.ShotNumberColumnVisibility, Source={x:Reference dummyElement}}" Binding="{Binding Path=ShotNumber}" Header="Shot #" />
</DataGrid.Columns>
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Header="Toggle Visibility">
<MenuItem Header="Shot Count" Command="{Binding ToggleVisibilityCommand}" />
</MenuItem>
</ContextMenu>
</DataGrid.ContextMenu>
</DataGrid >
В настоящее время мой View .xaml выглядит так же, как в приведенном выше примере, но с большим количеством столбцов и соответствующим элементом меню ContextMenu для каждого. В моей ViewModel я могу управлять видимостью, изменяя ShotNumberVisibility.
public MyViewModel()
{
ToggleVisibilityCommand = new RelayCommand(ToggleVisibility);
}
public Visibility ShotNumberColumnVisibility { get; set; } = Visibility.Visible;
public void ToggleVisibility(object obj)
{
ShotNumberColumnVisibility = ShotNumberColumnVisibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;
RaisePropertyChanged("ShotNumberColumnVisibility");
}
Я НЕ хочу настраивать это для каждого отдельного DataGridTextColumn. Каков правильный способ передать любой DataGridTextColumn в мою ViewModel, чтобы его видимость можно было переключать с помощью общего метода?
Из того, что я видел, похоже, что мне нужно использовать CommandParameter для отправки любого DataGridTextColumn в мою функцию ToggleVisibility. Это та часть, которую я не могу понять. Я думаю что-то вроде следующего в моем .xaml, но у меня это еще не сработало.
CommandParameter="{Binding ElementName=InclinationColumn, Path=Visibility}"
Если это все еще не ясно, вот некоторый псевдокод для команды, которую я хотел бы иметь, и как я хотел бы ее использовать.
<DataGridTextColumn Name="demoColumn" Visibility="{Binding demoColumnVisibility}" />
<MenuItem Header="Toggle Demo Column Visibility" CommandParameter="{Binding demoColumn.Visibility}" Command="{Binding ToggleVisibility}" />
public void ToggleVisibility(object obj)
{
obj.Visibility = !obj.Visibility
//OR MAYBE
//Pass in the name "demoColumn" and use that select which bool to flip. In this case demoColumnVisibility
}
Вот как выглядит мой класс RelayCommand:ICommand...
public class RelayCommand : ICommand
{
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if(execute == null)
{
throw new NullReferenceException("execute");
}
_execute = execute;
_canExecute = canExecute;
}
public RelayCommand(Action<object> execute) : this(execute, null)
{
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute.Invoke(parameter);
}
}
Надеюсь, этого достаточно, эта проблема убивала меня часами, и я чувствую, что упускаю что-то основное. Любая помощь горячо приветствуется.