WPF:绑定到 ContextMenu MenuItem 的 DataTrigger 只工作一次
WPF: DataTrigger bound to a ContextMenu MenuItem works only once
我试图用 DataTrigger
隐藏 Datagrid
中的列(绑定到 DataTable
)。以便用户可以选择显示哪些列。我的问题是这只有效一次。通常我会说我需要 INotifyPropertyChanged
,但是我的 ContextMenu
是在 XAML 中定义的,所以我不确定是否以及如何做到这一点。
这是我的XAML
<ContextMenu >
....
<MenuItem Header="Apply" x:Name="ButtonApply" />
</ContextMenu>
<DataGrid ItemsSource="{Binding Path=TabDataTable}" AutoGenerateColumns="True" IsReadOnly="True" SelectionUnit="CellOrRowHeader" Margin="-5,-4,-5,-4" AlternatingRowBackground="Gainsboro" x:Name="MainDataGrid">
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ButtonApply, Path=IsPressed}" Value="True">
<Setter Property="Visibility">
<Setter.Value>
<!--<Binding Path=" DataContext.IsTemplateColumnVisibile, Source={StaticResource ProxyElement}, Converter={StaticResource BooleanToVisibilityConverter}}" />-->
<MultiBinding Converter="{StaticResource BooleanToVisibilityConverter}">
<Binding Path="Column"
RelativeSource="{RelativeSource Self}"/>
<Binding Path="DataContext.visibility"
RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}"/>
</MultiBinding>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
</DataGrid>
这里是Converter
:(对不起,误导的名字)
public object Convert(object[] value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value[0] == null)
{
return null;
}
if ((((ObservableCollection<bool>)value[1]).ToArray())[((System.Windows.Controls.DataGridTextColumn)value[0]).DisplayIndex])
{
//Column Visibility
((System.Windows.Controls.DataGridTextColumn)value[0]).Visibility = Visibility.Visible;
//Header Visibility
return Visibility.Visible;
}
((System.Windows.Controls.DataGridTextColumn)value[0]).Visibility = Visibility.Collapsed;
return Visibility.Collapsed;
}
如果有更好的方法来完成这个,请随时为我指明正确的方向。
您可以使用 Attached Property 来控制列可见性
并将其绑定到实现 INotify属性Changed.
的列表
<Style TargetType="DataGrid">
<Setter Property="local:DataGridHelper.VisibilityList"
Value="{Binding NotifyingList}"/>
</Style>
附上属性
public class DataGridHelper : DependencyObject
{
public static List<bool> GetVisibilityList(
DependencyObject obj)
{
return (List<bool>)obj.GetValue(VisibilityListProperty);
}
public static void SetVisibilityList(
DependencyObject obj, List<bool> value)
{
obj.SetValue(VisibilityListProperty, value);
}
public static readonly DependencyProperty
VisibilityListProperty =
DependencyProperty.RegisterAttached("VisibilityList",
typeof(List<bool>), typeof(DataGridHelper),
new PropertyMetadata(VisibilityListChanged));
private static void VisibilityListChanged(DependencyObject d,
DependencyPropertyChangedEventArgs args)
{
var grid = d as DataGrid;
if (grid == null
|| grid.Columns.Count == 0
|| grid.Columns[0].DisplayIndex == -1) return;
var visibilities = (List<bool>)grid.GetValue(VisibilityListProperty);
foreach (var column in grid.Columns)
{
if ((bool)visibilities[column.DisplayIndex])
column.Visibility = Visibility.Visible;
else
column.Visibility = Visibility.Collapsed;
}
}
}
注意这里用的是column.DisplayIndex,所以DataGrid.CanUserReorderColumns应该是false。这应该可以让您继续,我建议您在处理上下文菜单之前尝试一下。
我试图用 DataTrigger
隐藏 Datagrid
中的列(绑定到 DataTable
)。以便用户可以选择显示哪些列。我的问题是这只有效一次。通常我会说我需要 INotifyPropertyChanged
,但是我的 ContextMenu
是在 XAML 中定义的,所以我不确定是否以及如何做到这一点。
这是我的XAML
<ContextMenu >
....
<MenuItem Header="Apply" x:Name="ButtonApply" />
</ContextMenu>
<DataGrid ItemsSource="{Binding Path=TabDataTable}" AutoGenerateColumns="True" IsReadOnly="True" SelectionUnit="CellOrRowHeader" Margin="-5,-4,-5,-4" AlternatingRowBackground="Gainsboro" x:Name="MainDataGrid">
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ButtonApply, Path=IsPressed}" Value="True">
<Setter Property="Visibility">
<Setter.Value>
<!--<Binding Path=" DataContext.IsTemplateColumnVisibile, Source={StaticResource ProxyElement}, Converter={StaticResource BooleanToVisibilityConverter}}" />-->
<MultiBinding Converter="{StaticResource BooleanToVisibilityConverter}">
<Binding Path="Column"
RelativeSource="{RelativeSource Self}"/>
<Binding Path="DataContext.visibility"
RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}"/>
</MultiBinding>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
</DataGrid>
这里是Converter
:(对不起,误导的名字)
public object Convert(object[] value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value[0] == null)
{
return null;
}
if ((((ObservableCollection<bool>)value[1]).ToArray())[((System.Windows.Controls.DataGridTextColumn)value[0]).DisplayIndex])
{
//Column Visibility
((System.Windows.Controls.DataGridTextColumn)value[0]).Visibility = Visibility.Visible;
//Header Visibility
return Visibility.Visible;
}
((System.Windows.Controls.DataGridTextColumn)value[0]).Visibility = Visibility.Collapsed;
return Visibility.Collapsed;
}
如果有更好的方法来完成这个,请随时为我指明正确的方向。
您可以使用 Attached Property 来控制列可见性 并将其绑定到实现 INotify属性Changed.
的列表<Style TargetType="DataGrid">
<Setter Property="local:DataGridHelper.VisibilityList"
Value="{Binding NotifyingList}"/>
</Style>
附上属性
public class DataGridHelper : DependencyObject
{
public static List<bool> GetVisibilityList(
DependencyObject obj)
{
return (List<bool>)obj.GetValue(VisibilityListProperty);
}
public static void SetVisibilityList(
DependencyObject obj, List<bool> value)
{
obj.SetValue(VisibilityListProperty, value);
}
public static readonly DependencyProperty
VisibilityListProperty =
DependencyProperty.RegisterAttached("VisibilityList",
typeof(List<bool>), typeof(DataGridHelper),
new PropertyMetadata(VisibilityListChanged));
private static void VisibilityListChanged(DependencyObject d,
DependencyPropertyChangedEventArgs args)
{
var grid = d as DataGrid;
if (grid == null
|| grid.Columns.Count == 0
|| grid.Columns[0].DisplayIndex == -1) return;
var visibilities = (List<bool>)grid.GetValue(VisibilityListProperty);
foreach (var column in grid.Columns)
{
if ((bool)visibilities[column.DisplayIndex])
column.Visibility = Visibility.Visible;
else
column.Visibility = Visibility.Collapsed;
}
}
}
注意这里用的是column.DisplayIndex,所以DataGrid.CanUserReorderColumns应该是false。这应该可以让您继续,我建议您在处理上下文菜单之前尝试一下。