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

bweufnob  于 2023-09-28  发布在  其他
关注(0)|答案(8)|浏览(107)

我有一个使用AutoGenerateColumns=True绑定到DataTable的WPF 4.0 DataGrid。列是动态的,但是我知道总是会有一个名为ID的列,我想隐藏这个列。有什么办法可以让我这么做吗?

uqcuzwp8

uqcuzwp81#

在你的数据网格中,订阅AutoGeneratingColumn事件,事件argsDataGridAutoGeneratingColumnEventArgs)有列名和一个“Cancel“,如果列名是ID则设置Cancel = true。应该可以

pepwfjgg

pepwfjgg2#

你可以使用一个行为(可重用代码)来完成这项工作……这样你就可以使用attribute来将列的可见性集中在一个地方。
使用方法:

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

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

...

public class YourObjectItem
{
    [Browsable(false)]
        public Assembly Assembly { get; set; }

代码:

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

kuhbmx9i3#

另一种可能性是Visibility.Collapsed

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

eit6fx6z4#

我不认为这是个好办法...但是.你可以多一个抽象层,比如说你有一个像这样的对象:

public class Foo
{
    public string Id { get; set; }

    public string Property2 { get; set; }

    public string Property3 { set; get; }
}

您不希望ID为column,因此创建了新对象

public class Foo2
{
    public string Property2 { get; set; }

    public string Property3 { set; get; }
}

然后将FooMap/转换为Foo 2,就完成了。
另一种可能的方法 (并不总是可能的) 是将访问修饰符更改为internal

public class Foo
{
    internal string Id { get; set; }

    public string Property2 { get; set; }

    public string Property3 { set; get; }
}

这样你也不会生成Id列。

wqlqzqxt

wqlqzqxt5#

我使用Browsable属性和Visibility: Collapsed实现了这一点
模型

class CourseModel
{
    [Description("")]
    [ReadOnly(false)]
    public bool Select { get; set; } = true; // Checkbox

    [Description("Course ID")]
    [ReadOnly(true)]
    [Browsable(false)]
    public string ID { get; set; } // Hidden column

    [Description("Course Title")]
    [ReadOnly(true)]
    public string Title { get; set; }
}

自定义控件扩展:

using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;

namespace MyProject.FrontEnd.Controls
{
    class CustomDataGrid : DataGrid
    {
        // Take attributes of POCO, if available (https://stackoverflow.com/a/17255496/979621)

        protected override void OnAutoGeneratingColumn(DataGridAutoGeneratingColumnEventArgs e)
        {
            try
            {
                base.OnAutoGeneratingColumn(e);
                var propertyDescriptor = e.PropertyDescriptor as PropertyDescriptor;
                e.Column.Header = propertyDescriptor.Description;
                e.Column.IsReadOnly = propertyDescriptor.IsReadOnly;
                e.Column.Visibility = propertyDescriptor.IsBrowsable 
                                      ? Visibility.Visible 
                                      : Visibility.Collapsed;
            }
            catch
            {
                // ignore; retain field defaults
            }
        }
    }
}

ViewModel

public ObservableCollection<CourseModel> Courses { get; set; }

XAML

<Window 
    ...
    xmlns:controls="clr-namespace:MyProject.FrontEnd.Controls" 
    ...
>
...
<controls:CustomDataGrid x:Name="courses" 
    ItemsSource="{Binding Path=Courses, Mode=TwoWay, 
                  NotifyOnSourceUpdated=True, NotifyOnTargetUpdated=True}" />
blmhpbnm

blmhpbnm6#

我不能说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}"/>

这将允许您显示与基础模型相关的唯一列,并将Header更改为您认为合适的显示,这样您就不会被模型上的Property名称所束缚。

oiopk7p5

oiopk7p57#

我最近做了这个,想分享我的解决方案:
我只是创建了一个视图模型,希望datagrid遵循这个模型,并且对于我希望它忽略的字段(也就是说,不自动生成列),只需将这些字段设置为private。工作起来很有魅力,不需要不必要的代码。
例如,下面是我传递给包含数据网格的视图的视图模型。只需将不希望作为列的字段设置为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");
    }
}
qybjjes1

qybjjes18#

AutoGeneratingColumn="DataGridAutoGenColumnEvent" add it to XAML

并在代码端粘贴它并替换您的模型值以跳过:

List<string> HeadersToSkip = new List<string> { "StockStatus" , "ImagePath" , "SupplyID" , "RemarksJson" , "PurchaseRequetID" , "DocumentsFolderPath" ,"" };

            if (HeadersToSkip.Contains( e.Column.Header.ToString()))
            {
                e.Cancel = true;
            }

相关问题