0

So I am using WPF (actually C# as a whole) for the first time and I'm struggling with a Datagrid that I want to customize.

 public MainWindow()
    {
        InitializeComponent();
        animalsGrid.ItemsSource = ViewModel.getAnimalsList();
        ScrollPane.Content = animalsGrid;
    }

And here's the Animal Class :

public class Animal() {
    string name;
    string race;
    string habitat;
    string age;
    /*
     * constructor, methods etc
     */
}

As you can see I'm populating my Datagrid with a list of Animals that have a bunch of specifications (Fields). The users don't need all of these specifications. How do I make sure only some fields are displayed in the Datagrid ? i.e only name and race

AniMir
  • 150
  • 12

2 Answers2

1

You got a few options here, only public properties should be created as columns if you define autogeneratedcolumns as true in your xaml. Also you could write a behaviour that inspects stuff before the column here created here you could even create custom attributes for this. That all said the most common way to get started is to set autogeneratedcolumns to false and create all the columns you want to display in your xaml and bind the properties of your items explicit to the columns.

update for properties and attributes

public class Animal() {
string name;


[Browsable(false)]
public string Name ...

}

This attribute would prevent the catalytic to render this property as a column if you used autogeneratedcolumns. Of course in didn't put a full example here

Update for Behaviour

If you like to use a custom Behaviour for your grid you could do something like that

namespace yourApp.Infrastructure
{

    public class HideAutogeneratedColumsBehaviour : Behavior<DataGrid>
    {

        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.AutoGeneratingColumn += new EventHandler<DataGridAutoGeneratingColumnEventArgs>(DataGridOnAutoGeneratingColumn);
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();
            AssociatedObject.AutoGeneratingColumn -= new EventHandler<DataGridAutoGeneratingColumnEventArgs>(DataGridOnAutoGeneratingColumn);
        }

        private static void DataGridOnAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
        {
            if (e.PropertyDescriptor is PropertyDescriptor propDesc)
            {
                 // DO things 

            }
        }
    }
}

than use it in your XAML by adding the namespace to your Window class

    xmlns:infrastructure="clr-namespace:yourApp.Infrastructure"

and on your Datagrid, note that this is not complete and you need to add the namespace for interactions too.

<DataGrid AutoGenerateColumns="True">
    <i:Interaction.Behaviors>
        <infrastructure:HideAutogeneratedColumsBehaviour />
    </i:Interaction.Behaviors>
</DataGrid>

if you like to use a custom Attribute to check in your behaviour then you could do something like that.

namespace yourApp.Infrastructure
{
    [AttributeUsage(AttributeTargets.Property)]
    public class YourCustomAttribute : Attribute
    {
        private string attributeValue;


        public YourCustomAttribute(string value)
        {
            attributeValue = value;

        }

        public string AttributeValue{ get => name; }

    }
}

and use it in your code on a Property

    [YourCustomAttribute("foo")]
    public string MyProperty { get => myProperty; set { myProperty = value; } } 

again just an example, and then do the checking in your behaviour

if (e.PropertyDescriptor is PropertyDescriptor propDesc)
{
    foreach (Attribute att in propDesc.Attributes)
    {
        if(att is YourCustomAttrbute customAttr)
        {
           // do something
        }
    }
}

so I hope you get some ideas out of my update how to customize your Columns.

Markus Rosjat
  • 146
  • 2
  • 8
0

I would suggest to add a custom attribute to indicate what columns to hide:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace CustomizeDataGrid
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            IList<Animal> animals = new List<Animal>() { new Animal("Tiget", "race1", "habitat1", "12"), new Animal("Cat", "race2", "habitat2", "23"), };
            Animals = CollectionViewSource.GetDefaultView(animals);

            InitializeComponent();
            dataGrid1.ItemsSource = Animals;
        }

        private void dataGrid1_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
        {
            if (e.PropertyDescriptor is PropertyDescriptor prop && prop.Attributes.OfType<HiddenAttribute>().Any())
            {
                e.Cancel = true;                
            }
        }

        public ICollectionView Animals { get; set; }
    }


    public class Animal
    {
        public Animal(string name, string race, string habitat, string age)
        {
            Name = name;
            Race = race;
            Habitat = habitat;
            Age = age;
        }

        public string Name { get; set; }
        [Hidden]
        public string Race { get; set; }
        public string Habitat { get; set; }
        public string Age { get; set; }
    }

    public class HiddenAttribute : Attribute
    {       
    }
}

XAML:

DataGrid x:Name="dataGrid1" AutoGenerateColumns="True" AutoGeneratingColumn="dataGrid1_AutoGeneratingColumn"/>
Jackdaw
  • 7,626
  • 5
  • 15
  • 33