Search code examples
c#wpfxamldatagriditemssource

How do you bind an ObservableCollection of a custom data type to a datagrid?


I am trying to create a datagrid for a circuit diagram project I am working on, it should have four columns: Name, Resistance, Voltage, Active. (string, float, float, bool). I have tried everything I could find online to bind these.

The setup I am using is as such:

My xaml window:

<DataGrid x:Name="ComponentDataGrid" AutoGenerateColumns="False" IsReadOnly="False" SelectionChanged="ComponentDataGrid_SelectionChanged">
   <DataGrid.Columns>
      <DataGridTextColumn x:Name="String1" Binding="{Binding Name}"/>
      <DataGridTextColumn x:Name="String2" Binding="{Binding Resistance}"/>
      <DataGridTextColumn x:Name="Int1" Binding="{Binding Voltage}"/>
      <DataGridTextColumn x:Name="Bool1" Binding="{Binding Active}"/>
   </DataGrid.Columns>
</DataGrid>

My class to handle the observablecollection

internal static class DataGridHandler
    {
        public static ObservableCollection<ComponentDisplayData> DisplayData = new ObservableCollection<ComponentDisplayData>();
        public static void AddNewComponentData(Component component)
        {
            ComponentDisplayData data = new ComponentDisplayData(component);
            DisplayData.Add(data);

        }

        public static ObservableCollection<ComponentDisplayData> LoadCollectionData()
        {
            Console.WriteLine("Loaded");
            return DisplayData;
        }
    }

My class to store the properties that should be used in each row:

    public class ComponentDisplayData
    {
        public string Name;
        public float Resistance;
        public float Voltage;
        public bool Active;

        public ComponentDisplayData(Component component)
        {
            Name = component.name;
            Resistance = component.Resistance;
            if (component is Cell)
            {
                Voltage = ((Cell)component).Voltage;
            }
            else
            {
                Voltage = 0;
            }
            Active = component.Active;
        }
    }

and my window class that binds the collection to the datagrid:

public Workspace()
        {
            InitializeComponent();
            ComponentDataGrid.DataContext = DataGridHandler.LoadCollectionData();
            ComponentDataGrid.ItemsSource = DataGridHandler.LoadCollectionData();
        }

When i call DataGridHandler.AddNewComponentData(component) it adds a new row to the grid, with 4 blank cells. Also when I iterate through the ComponentDataGrid.ItemsSource after adding a component, the component data is stored properly and I can write the data to the console, it just won't appear in the grid.


Solution

  • As @emoacht said using a property rather than a field fixed the problem:

    public class ComponentDisplayData
    {
        public string Name { get; set; }
        public float Resistance { get; set; }
        public float Voltage { get; set; }
        public bool Active { get; set; }
    
        public ComponentDisplayData(Component component)
        {
            Name = component.name;
            Resistance = component.Resistance;
            if (component is Cell)
            {
                Voltage = ((Cell)component).Voltage;
            }
            else
            {
                Voltage = 0;
            }
            Active = component.Active;
        }
    }
    

    Changing the fields to properties by adding { get; set; } after them fixed my issue.