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。这应该可以让您继续,我建议您在处理上下文菜单之前尝试一下。