【发布时间】:2020-02-07 04:14:36
【问题描述】:
我有一个 DataGrid,并希望使用从 ContextMenu 发送的命令来切换各个 DataGridTextColumns 的可见性。我需要某种方法将特定的 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 MenuItem。在我的 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);
}
}
希望这已经足够了,这个问题已经困扰了我好几个小时,我觉得我错过了一些基本的东西。非常感谢任何帮助。
【问题讨论】:
标签: c# wpf mvvm data-binding commandparameter