Wpf 当AutoGenerateColumns=True时,是否有方法隐藏DataGrid中的特定列?

Wpf 当AutoGenerateColumns=True时,是否有方法隐藏DataGrid中的特定列?,wpf,xaml,datagrid,Wpf,Xaml,Datagrid,我有一个WPF4.0DataGrid,它使用AutoGenerateColumns=True绑定到一个DataTable。这些列是动态的,但是我知道总是会有一个名为ID的列,我想隐藏这个列。有什么方法可以做到这一点吗?我不能说4,但是在3.5 SP1中这是不可能的,至少在没有注册我想不惜一切代价避免的事件的情况下是不可能的 您可以改为将生成代码更改为AutoGenerateColumns=False,然后只需将您关心的列放在XAML中,因为基础数据仍将适当地放在列中 &l

我有一个WPF4.0DataGrid,它使用AutoGenerateColumns=True绑定到一个DataTable。这些列是动态的,但是我知道总是会有一个名为ID的列,我想隐藏这个列。有什么方法可以做到这一点吗?

我不能说4,但是在3.5 SP1中这是不可能的,至少在没有注册我想不惜一切代价避免的事件的情况下是不可能的

您可以改为将生成代码更改为
AutoGenerateColumns=False
,然后只需将您关心的列放在XAML中,因为基础数据仍将适当地放在列中

            <dg:DataGridTextColumn Header="Display" Binding="{Binding DisplayName}"/>
            <dg:DataGridTextColumn Header="Host" Binding="{Binding HostName}"/>
            <dg:DataGridTextColumn Header="Database" Binding="{Binding Database}"/>
            <dg:DataGridTextColumn Header="Username" Binding="{Binding Username}"/>
            <dg:DataGridTextColumn Header="Password" Binding="{Binding Password}"/>


这将允许您仅显示您关心的与基础模型相关的列,并将
标题更改为显示您认为合适的列,这样您就不会被绑定到模型上的
属性名称上。

在数据网格中,订阅
自动生成列
事件,事件
args
DataGridAutoGeneratingColumnEventArgs
)具有列名和“
Cancel
”,如果列名是ID,则设置
Cancel=true
。应该可以做到这一点。

我不会说这是一个很好的解决方案。。。但是您还可以有一个抽象层 例如,假设您有一个对象,如:

公共类Foo
{
公共字符串Id{get;set;}
公共字符串属性2{get;set;}
公共字符串属性3{set;get;}
}
您不希望Id为列,所以创建新对象

公共类Foo2
{
公共字符串属性2{get;set;}
公共字符串属性3{set;get;}
}
然后将Foo映射/转换为Foo2,就完成了

另一种可能的方法(并非总是可能的)是将访问修饰符更改为内部

公共类Foo
{
内部字符串Id{get;set;}
公共字符串属性2{get;set;}
公共字符串属性3{set;get;}
}

这样您也不会生成Id列。

其他可能是
可见性。折叠的

    private void dataGrid_AutoGeneratingColumn(object sender, 
        DataGridAutoGeneratingColumnEventArgs e)
    {
        //Set properties on the columns during auto-generation 
        switch (e.Column.Header.ToString())
        {
            case "rownameYouWantToHide":
                e.Column.Visibility = Visibility.Collapsed;
                break;
        }
    }
您可以使用行为(可重用代码)来完成此工作。。。通过这种方式,您可以使用将列可见性集中在一个位置的属性

用法:

<Window
...
 xmlns:extension="clr-namespace:WpfControlLibrary.Extension;assembly=WpfControlLibrary">

<DataGrid ...
    extension:DataGridBehavior.UseBrowsableAttributeOnColumn="True">
代码:

使用系统;
使用系统组件模型;
使用System.Windows;
使用System.Windows.Controls;
命名空间HQ.Wpf.Util.Behaviors
{
/// 
///在dataGRid上使用此行为将确保仅显示具有“可浏览属性”的列
/// 
公共静态类DataGridBehavior
{
公共静态只读从属属性UseBrowsableAttributeOnColumnProperty=
DependencyProperty.RegisterAttached(“UseBrowsableAttributeOnColumn”,
类型(bool),
类型(DataGridBehavior),
新的UIPropertyMetadata(false,UseBrowsableAttributeOnColumnChanged));
公共静态bool GetUseBrowsableAttribute列(DependencyObject obj)
{
返回(bool)对象GetValue(UseBrowsableAttributeOnColumnProperty);
}
公共静态无效集合UseBrowsableAttributeOnColumn(DependencyObject对象,布尔值)
{
对象设置值(UseBrowsableAttributeOnColumnProperty,val);
}
私有静态无效UseBrowsableAttributeOnColumnChanged(DependencyObject对象,DependencyPropertyChangedEventArgs e)
{
var dataGrid=obj作为dataGrid;
if(dataGrid!=null)
{
if((bool)e.NewValue)
{
dataGrid.AutoGeneratingColumn+=DataGridOnAutoGeneratingColumn;
}
其他的
{
dataGrid.AutoGeneratingColumn-=DataGridOnAutoGeneratingColumn;
}
}
}
私有静态void DataGridOnAutoGeneratingColumn(对象发送方,DataGridAutoGeneratingColumnEventArgs e)
{
var propDesc=e.PropertyDescriptor作为PropertyDescriptor;
如果(propDesc!=null)
{
foreach(propDesc.Attributes中的属性att)
{
var browsableAttribute=作为browsableAttribute的附件;
if(browsableAttribute!=null)
{
如果(!browsableAttribute.Browsable)
{
e、 取消=真;
}
}
//根据“dba”stackoverflow用户在网页上的建议:
// https://stackoverflow.com/questions/4000132/is-there-a-way-to-hide-a-specific-column-in-a-datagrid-when-autogeneratecolumns
//接下来我添加了几行:
var displayName=att作为displayName属性;
if(displayName!=null)
{
e、 Column.Header=displayName.displayName;
}
}
}
}
}
}

我最近完成了这项工作,希望与大家分享我的解决方案:

我刚刚创建了一个视图模型,我希望datagrid遵循它,对于我希望它忽略的字段(即,不是自动生成列),只需将这些字段设置为private即可。工作起来很有魅力,不需要不必要的代码

例如,下面是我传递给包含datagrid的视图的视图模型。我只需将我不想作为列的字段设置为private即可获得所需的一切,如我的示例中的“FullPath”字段所示。我知道这可能不可能在所有情况下都实现,但对我来说效果很好

namespace dev
{   
    /// <summary>
    /// View model for tag list view in data grid
    /// </summary>
    public class TagDataViewModel : BaseViewModel
    {
        /// <summary>
        /// Default constructor
        /// </summary>
        /// <param name="path">The JSONPath to this item</param>
        public TagDataViewModel(string path)
        {
            FullPath = path;
        }

        /// <summary>
        /// Gets and sets the JSONPath to this item
        /// </summary>
        private string FullPath { get; set; }

        /// <summary>
        /// Gets the name
        /// </summary>
        public string Name => ProjectHelpers.GetPropertyValue(FullPath, "Name");

        /// <summary>
        /// Gets the address
        /// </summary>
        public string Address => ProjectHelpers.GetPropertyValue(FullPath, "Address");

        /// <summary>
        /// Gets the data type
        /// </summary>
        public string DataType => ProjectHelpers.GetPropertyValue(FullPath, "DataType");

        /// <summary>
        /// Gets the scan rate
        /// </summary>
        public string ScanRate => ProjectHelpers.GetPropertyValue(FullPath, "ScanRate");

        /// <summary>
        /// Gets the scaling type
        /// </summary>
        public string ScalingType => ProjectHelpers.GetPropertyValue(FullPath, "ScalingType");
    }
}
名称空间开发
{   
/// 
///数据网格中标记列表视图的视图模型
/// 
公共类TagDataViewModel:BaseViewModel
{
/// 
///默认构造函数
/
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;

namespace HQ.Wpf.Util.Behaviors
{
    /// <summary>
    /// Using this behavior on a dataGRid will ensure to display only columns with "Browsable Attributes"
    /// </summary>
    public static class DataGridBehavior
    {
        public static readonly DependencyProperty UseBrowsableAttributeOnColumnProperty =
            DependencyProperty.RegisterAttached("UseBrowsableAttributeOnColumn",
            typeof(bool),
            typeof(DataGridBehavior),
            new UIPropertyMetadata(false, UseBrowsableAttributeOnColumnChanged));

        public static bool GetUseBrowsableAttributeOnColumn(DependencyObject obj)
        {
            return (bool)obj.GetValue(UseBrowsableAttributeOnColumnProperty);
        }

        public static void SetUseBrowsableAttributeOnColumn(DependencyObject obj, bool val)
        {
            obj.SetValue(UseBrowsableAttributeOnColumnProperty, val);
        }

        private static void UseBrowsableAttributeOnColumnChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var dataGrid = obj as DataGrid;
            if (dataGrid != null)
            {
                if ((bool)e.NewValue)
                {
                    dataGrid.AutoGeneratingColumn += DataGridOnAutoGeneratingColumn;
                }
                else
                {
                    dataGrid.AutoGeneratingColumn -= DataGridOnAutoGeneratingColumn;
                }
            }
        }

        private static void DataGridOnAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
        {
            var propDesc = e.PropertyDescriptor as PropertyDescriptor;

            if (propDesc != null)
            {
                foreach (Attribute att in propDesc.Attributes)
                {
                    var browsableAttribute = att as BrowsableAttribute;
                    if (browsableAttribute != null)
                    {
                        if (!browsableAttribute.Browsable)
                        {
                            e.Cancel = true;
                        }
                    }

                    // As proposed by "dba" stackoverflow user on webpage: 
                    // https://stackoverflow.com/questions/4000132/is-there-a-way-to-hide-a-specific-column-in-a-datagrid-when-autogeneratecolumns
                    // I added few next lines:
                    var displayName = att as DisplayNameAttribute;
                    if (displayName != null)
                    {
                        e.Column.Header = displayName.DisplayName;
                    }
                }
            }
        }
    }
}
namespace dev
{   
    /// <summary>
    /// View model for tag list view in data grid
    /// </summary>
    public class TagDataViewModel : BaseViewModel
    {
        /// <summary>
        /// Default constructor
        /// </summary>
        /// <param name="path">The JSONPath to this item</param>
        public TagDataViewModel(string path)
        {
            FullPath = path;
        }

        /// <summary>
        /// Gets and sets the JSONPath to this item
        /// </summary>
        private string FullPath { get; set; }

        /// <summary>
        /// Gets the name
        /// </summary>
        public string Name => ProjectHelpers.GetPropertyValue(FullPath, "Name");

        /// <summary>
        /// Gets the address
        /// </summary>
        public string Address => ProjectHelpers.GetPropertyValue(FullPath, "Address");

        /// <summary>
        /// Gets the data type
        /// </summary>
        public string DataType => ProjectHelpers.GetPropertyValue(FullPath, "DataType");

        /// <summary>
        /// Gets the scan rate
        /// </summary>
        public string ScanRate => ProjectHelpers.GetPropertyValue(FullPath, "ScanRate");

        /// <summary>
        /// Gets the scaling type
        /// </summary>
        public string ScalingType => ProjectHelpers.GetPropertyValue(FullPath, "ScalingType");
    }
}
<Window 
    ...
    xmlns:controls="clr-namespace:MyProject.FrontEnd.Controls" 
    ...
>
...
<controls:CustomDataGrid x:Name="courses" 
    ItemsSource="{Binding Path=Courses, Mode=TwoWay, 
                  NotifyOnSourceUpdated=True, NotifyOnTargetUpdated=True}" />