WPF:绑定到ContextMenu MenuItem的DataTrigger仅工作一次 [英] WPF: DataTrigger bound to a ContextMenu MenuItem works only once

查看:116
本文介绍了WPF:绑定到ContextMenu MenuItem的DataTrigger仅工作一次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用DataTrigger隐藏Datagrid中的列(绑定到DataTable).这样用户可以选择显示哪些列.我的问题是,这只能工作一次.通常,我会说我需要INotifyPropertyChanged,但是我的ContextMenu是在XAML中定义的,因此我不确定是否以及如何执行.

I am trying to hide colummns in a Datagrid (bound to a DataTable) with DataTrigger. So that the user can choose which columns are displayed. My problem is that this only works once. Normaly I would say that I need the INotifyPropertyChanged, however my ContextMenu is defined in XAML so I am not sure if and how to do that.

这是我的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 :(对具有误导性的名称表示歉意)

Here the Converter: (Sry for the misleading name)

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;
}  

如果有更好的方法可以做到这一点,请随时指出正确的方向.

If there is a better way to accomplish this, please feel free to point me in the right direction.

推荐答案

您可以使用附加属性控制列的可见性 并将其绑定到实现INotifyPropertyChanged的列表.

You can use an Attached Property to control Column visibility and bind it to a list implementing INotifyPropertyChanged.

<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.这应该可以帮助您,我建议您在尝试使用ContextMenu之前先尝试一下.

Note that column.DisplayIndex is used, so DataGrid.CanUserReorderColumns should be false. This should get you going, I suggest you try it out before you tackle the ContextMenu.

这篇关于WPF:绑定到ContextMenu MenuItem的DataTrigger仅工作一次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆