[ACCEPTED]-Is there a way to hide a specific column in a DataGrid when AutoGenerateColumns=True?-datagrid
in your datagrid, subscribe for the AutoGeneratingColumn
event, the 3 event args
(DataGridAutoGeneratingColumnEventArgs
) has the column name and a "Cancel
", if 2 the column name is ID then set Cancel = true
. should 1 do the trick.
You can use a behavior (reusable code) to 3 do the job... This way you can use attribute 2 which would centralize the column visibility 1 in one place.
Usage:
<Window
...
xmlns:extension="clr-namespace:WpfControlLibrary.Extension;assembly=WpfControlLibrary">
<DataGrid ...
extension:DataGridBehavior.UseBrowsableAttributeOnColumn="True">
...
public class YourObjectItem
{
[Browsable(false)]
public Assembly Assembly { get; set; }
Code:
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;
}
}
}
}
}
}
Other possibility would be 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;
}
}
0
I wouldn't say it's great solution... but... you 7 can have one more abstraction layer for 6 example let's say you have an object like:
public class Foo
{
public string Id { get; set; }
public string Property2 { get; set; }
public string Property3 { set; get; }
}
You 5 don't want column for Id, so you create 4 new object
public class Foo2
{
public string Property2 { get; set; }
public string Property3 { set; get; }
}
then map/convert Foo to Foo2 and 3 you are done.
Another possible way (not always possible) is to 2 change access modifier to internal
public class Foo
{
internal string Id { get; set; }
public string Property2 { get; set; }
public string Property3 { set; get; }
}
this way you won't 1 have Id column generated either.
I achieved this using Browsable
attribute and Visibility: Collapsed
Model
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; }
}
Custom 1 control extension:
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}" />
I can't speak for 4, however it was not 12 possible in 3.5 SP1, at least without registering 11 for an event which I wanted to avoid at 10 all costs.
What you could do instead is 9 change your generation code to AutoGenerateColumns=False
then just 8 place the columns you care about within 7 the XAML as the underlying data will all 6 still be placed within the columns appropriately 5
<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}"/>
This will allow you to display the only 4 columns you care about in relation to the 3 underlying model as well as change the Header
to 2 display as you see fit, so you are not tied 1 to the Property
name on the model.
I've recently done this and wanted to share 13 my solution:
I just made a view model I wanted 12 the datagrid to follow and for the fields 11 I wanted it to ignore (that is, not auto 10 generate columns for), simply set those 9 fields to private. Worked like a charm and 8 there's no need for unnecessary code.
For 7 example, here's the view model I pass to 6 the view that contains the datagrid. I get 5 all I need by simply setting the fields 4 I don't want as columns to private, shown 3 on the "FullPath" field in my example. I 2 understand this may not be possible in every 1 scenario, but worked for me quite well.
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");
}
}
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.