MDSBP MDSBP - 2 months ago 20
C# Question

Bind DataGrid to ObservableCollection of strings within another object

I have an object which contains an observable collection of strings, how do I bind a data grid to display those strings?

Take for example:

public class Container
{
public ObservableCollection<string> strs; //This won't work, see edit!
.
.
.
}


XAML:

<DataGrid ItemsSource="{Binding Container}" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn Header="Strings" Binding="{Binding}" />
</DataGrid.Columns>
</Datagrid>


Edit for the searchers: There are a few things wrong with the above approach, first you can bind to properties of items by simply referencing those properties. In this case:

ItemsSource="{Binding Container.strs}"


Second, the content of a string isn't a property of the string, so

Binding="{Binding}"


Binds directly to the string, instead of trying to find it's properties (such as Length)

Finally you cannot Bind to fields, only Properties, whats the difference?

public ObservableCollection<string> strs; //This is a field
public ObservableCollection<string> strs {get; set;} //This is property


Bonus: If you are just instantiating strs once then the ObservableCollection will notify whatever its bound to when changed to/within it occur, but if you are changing the pointer it won't, to fix this you can use a dependancy property!

In visual studio it's best to use the built in snippet for this as there are a lot of things to fill in type: 'propdp' and hit tab twice, in this case we'd have:

public ObservableCollection<string> strs
{
get { return (ObservableCollection<string>)GetValue(strsProperty); }
set { SetValue(strsProperty, value); }
}

// Using a DependencyProperty as the backing store for strs. This enables animation, styling, binding, etc...
public static readonly DependencyProperty strsProperty =
DependencyProperty.Register("strs", typeof(ObservableCollection<string>), typeof(Container), new PropertyMetadata(""));

Answer

This worked for me.

XAML:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication2"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>

        <DataGrid ItemsSource="{Binding thing.stuff}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTemplateColumn Width="Auto" Header="String Contents" >
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>

    </Grid>
</Window>

and code behind (C#):

using System.Windows;
using System.Collections.ObjectModel;

namespace WpfApplication2
{
    public class Thing
    {
        // make sure this is a property, not a field.
        // furthermore, make sure it is public. 
        public ObservableCollection<string> stuff
        {
            get; set;
        }

        public Thing()
        {
            stuff = new ObservableCollection<string>();
            stuff.Add("A String");
            stuff.Add("Another String");
            stuff.Add("Yet Another String");
        }
    }

    public partial class MainWindow : Window
    {
        public Thing thing{get;set;}
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
            thing = new Thing();
        }
    }
}

I do recommend you flesh out your question a bit more. Remember, the goal of StackOverflow is that questions are helpful to OTHER users, as well as yourself.

EDIT: Terser XAML

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication2"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>

        <DataGrid ItemsSource="{Binding thing.stuff}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Width="Auto" Binding="{Binding}" Header="String Contents" />
            </DataGrid.Columns>
        </DataGrid>

    </Grid>
</Window>
Comments