【问题标题】:Show/Hide DataGrid Columns XAML显示/隐藏 DataGrid 列 XAML
【发布时间】:2015-08-17 18:08:55
【问题描述】:

我正在尝试使用允许用户显示/隐藏列的控件构建一个 DataGrid。我的 DataGrid 将有大约 40 列,并不是所有的时间都需要。我已经能够用一个使用 GridView 的 ListView 来做这件事。 代码如下:

<DataGrid Name="MyDataGrid" Grid.Row="2" Grid.Column="0" ItemsSource="{Binding ReportOrderingCustomersForSalesRepCollection}" Style="{DynamicResource styleDataGrid}" HeadersVisibility="All" AutoGenerateColumns="False" RowHeaderWidth="0" RowHeight="25">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Customer #" Binding="{Binding CustomerNumber}" Width="90" Visibility="{Binding ElementName=Visibility_Txt,Path=Text,Mode=OneWay}"/>
        <DataGridTextColumn Header="Customer Name" Binding="{Binding CustomerName}" Width="125" />
        <DataGridTemplateColumn Header="Email" CellTemplate="{StaticResource Email}" Width="150" />
    </DataGrid.Columns>
</DataGrid>
<!-- text box -->
<TextBox Name="Visiblility_Txt">
    <TextBox.Style>
        <Style TargetType="TextBox">
            <Style.Triggers>
                <DataTrigger Binding="{Binding ElementName=ColumnVisibilityCheck,Path=IsChecked}" Value="False">
                    <Setter Property="Text" Value="Collapsed" />
                </DataTrigger>
                <DataTrigger Binding="{Binding ElementName=ColumnVisibilityCheck,Path=IsChecked}" Value="True">
                    <Setter Property="Text" Value="Visible" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </TextBox.Style>
</TextBox>
<!-- checkbox -->
<CheckBox Content="Show/Hide Customer Number" Name="ColumnVisibilityCheck" IsChecked="True" />

所以我有一个 DataGrid 设置。第一个 DataGridTextColumn 上的 Visibility 属性设置为与“Visibility_Txt”的文本属性的绑定。该文本框上的文本将设置为 Collapsed 或 Visible,具体取决于 ColumnVisibilityCheck 是否被选中。

就像我说的,这适用于列表视图,为什么这不适用于 DataGrid?

【问题讨论】:

  • ViewModel/代码隐藏?而且您至少有 3 个网格行但没有行定义
  • 行从 ItemsSource 填充。我想显示/隐藏各个列。
  • 网格行与数据网格行不同:
  • 是的,我明白,我问的是如何在 DataGrid 中显示/隐藏列,请阅读帖子。与行无关。
  • 如果我们没有实际查看数据网格所需的代码,您希望我们如何帮助您?请提供使示例工作所需的一切。

标签: wpf xaml datagrid


【解决方案1】:

1:在 DataGrid 中应用以下行为

<i:Interaction.Behaviors>
    <b:DataGridColumnVisibilityBindingBehavior Binding="{Binding IsNameVisible}" 
ColumnIndex="3" />
    </i:Interaction.Behaviors>

3:这里是行为的实现

public class DataGridColumnVisibilityBindingBehavior : Behavior<DataGrid>
{
    private static readonly DependencyProperty ProxyProperty = DependencyProperty.RegisterAttached(
        "Proxy",
        typeof(object),
        typeof(DataGridColumnVisibilityBindingBehavior),
        new PropertyMetadata(OnGridProxyChanged));

    private static readonly DependencyProperty AssociatedBinderProperty = DependencyProperty.RegisterAttached(
        "AssociatedBinder",
        typeof(ColumnDataContextBinder),
        typeof(DataGridColumnVisibilityBindingBehavior),
        new PropertyMetadata(default(ColumnDataContextBinder)));

    public Binding Binding { get; set; }

    public int ColumnIndex { get; set; }

    protected override void OnAttached()
    {
        base.OnAttached();

        CheckProxyBound();

        var column = AssociatedObject.Columns[this.ColumnIndex];
        var columnBinder = new ColumnDataContextBinder(column, this.Binding)
            {
                DataContext = AssociatedObject.GetValue(ProxyProperty)
            };

        column.SetValue(AssociatedBinderProperty, columnBinder);
    }

    private static void OnGridProxyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var grid = (DataGrid)d;
        foreach (var column in grid.Columns)
        {
            var binder = (ColumnBinder)column.GetValue(AssociatedBinderProperty);
            if (binder != null)
            {
                binder.DataContext = e.NewValue;
            }
        }
    }

    private void CheckProxyBound()
    {
        if (AssociatedObject.GetBindingExpression(ProxyProperty) == null)
        {
            AssociatedObject.SetBinding(ProxyProperty, new Binding());
        }
    }

    private sealed class ColumnDataContextBinder : FrameworkElement
    {
        private static readonly DependencyProperty IsVisibleProperty = DependencyProperty.Register(
            "IsVisible",
            typeof(bool),
            typeof(ColumnDataContextBinder),
            new PropertyMetadata(true, (s, e) => ((ColumnDataContextBinder)s).OnVisibilityChanged()));

        private readonly DataGridColumn column;

        public ColumnDataContextBinder(DataGridColumn column, Binding binding)
        {
            column = column;

            SetBinding(IsVisibleProperty, binding);
        }

        private bool IsVisible
        {
            get { return (bool)GetValue(IsVisibleProperty); }
        }

        private void OnVisibilityChanged()
        {
            column.Visibility = IsVisible ? Visibility.Visible : Visibility.Collapsed;
        }
    }
}

3:我希望这能回答你的问题。

【讨论】:

  • 为了完整和清楚起见...常规绑定不适用于 DataGridColumns,因为它们位于可视化树之外并且没有 DataContext。 Saraf Behavior 通过创建一个充当 DataContext 的代理类来解决这个问题。
【解决方案2】:

能够找到有关此的更多信息。这个链接有一个很好的答案/解释。 datagridtextcolumn-visibility-binding

事实证明,DataGrid 的列没有出现在 DataGrid 的可视化树中。

但答案是在可见性绑定中使用 x:reference 和 BooleanToVisibilityConverter:

<DataGridTextColumn Header="Customer #" x:Name="CustNum_Col" Visibility="{Binding Source={x:Reference VisibilityCheck}, Path=IsChecked,Converter={StaticResource ObjectToVisibilityConverter}}" />

Visual Studio 将在绑定下方显示波浪线,表示“对象未设置为对象的实例”,但这似乎仍然有效。

【讨论】:

    【解决方案3】:

    只需将其 MaxWidth 属性设置为零,它就不会出现。

    DataGrid.Columns[IndexOfColumn].MaxWidth = 0;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-18
      • 1970-01-01
      • 2013-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多