代码之家  ›  专栏  ›  技术社区  ›  nick9999

WPF:绑定到ContextMenu MenuItem的DataTrigger仅工作一次

  •  0
  • nick9999  · 技术社区  · 8 年前

    我想把柱子藏在一个 Datagrid (绑定到 DataTable )带有 DataTrigger 。以便用户可以选择要显示的列。我的问题是这只起一次作用。通常我会说我需要 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 :(Sry代表误导性名称)

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

    如果有更好的方法来实现这一点,请随时为我指出正确的方向。

    1 回复  |  直到 8 年前
        1
  •  0
  •   Funk    8 年前

    您可以使用 Attached Property 控制列可见性 并将其绑定到实现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;
            }
        }
    }
    

    请注意该列。使用了DisplayIndex,因此使用了DataGrid。CanUserReorderColumns应为false。这应该可以让你开始,我建议你在处理ContextMenu之前先尝试一下。