Setting a Valid ItemsSource for the DataGrid Design Time

In order to edit the Columns collection through the designer, the DataGrid must have a valid ItemsSource set. There is a limitation in the designer whereby you cannot bind to properties on the element you are designing. For example, it is common to do the following:

1. Declare a collection of items in the code behind of your Window1 file:

public partial class Window1 : WindowBase
{
public Window1()
{
InitializeComponent();
}

public class PeopleCollection : ObservableCollection<Person> {
public PeopleCollection() :base() {
var person = new Person();
person.FirstName = "test";
Add(person);
}
}

}

2. Bind DataGrid's ItemsSource to the collection in your Window1 code behind:

<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:Microsoft.Windows.Controls;assembly=WpfToolkit"
xmlns:local="clr-namespace:WpfApplication1"
x:Name="win">

<Grid>
<my:DataGrid ItemsSource="{Binding ElementName=win, Path=People}"></my:DataGrid>
</Grid>
</Window>

This will not work because DataGrid is bound to the People property on Window1, which is the element you are currently designing. There are two solutions to this problem. You can move the declaration of the item collection into the XAML, or alternatively you can put the property declaration into a base class:

Option 1 - Move the declaration of the collection into the XAML:

public class PeopleCollection : ObservableCollection<Person> {
public PeopleCollection() :base() {
var person = new Person();
person.FirstName = "test";
Add(person);
}
}

<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:Microsoft.Windows.Controls;assembly=WpfToolkit"
xmlns:local="clr-namespace:WpfApplication1"
x:Name="win">

<Window.Resources>
<local:PeopleCollection x:Key="People"/>
</Window.Resources>

<Grid>
<my:DataGrid ItemsSource="{Binding Source={StaticResource People}}"></my:DataGrid>
</Grid>
</Window>

Option 2 - Put the property declaration on a base class:

public partial class WindowBase : Window, INotifyPropertyChanged {
ObservableCollection<Person> _people;
public ObservableCollection<Person> People {
get {
return _people;
}
set {
_people = value;
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs("People"));
}
}
}

public WindowBase() : base() {
People = new ObservableCollection<Person>();
var person = new Person();
person.FirstName = "test";
People.Add(person);
}

#region INotifyPropertyChanged Members

public event PropertyChangedEventHandler PropertyChanged;

#endregion
}

public partial class Window1 : WindowBase
{

public Window1()
{
InitializeComponent();
}
}


<local:WindowBase x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:Microsoft.Windows.Controls;assembly=WpfToolkit"
xmlns:local="clr-namespace:WpfApplication1"
x:Name="win">

<Grid>
<my:DataGrid ItemsSource="{Binding ElementName=win, Path=People}"></my:DataGrid>
</Grid>
</local:WindowBase>

Last edited Oct 22, 2008 at 7:40 PM by SamanthaMSFT, version 1

Comments

Mike_BB Oct 31, 2008 at 8:52 AM 
Add IsAsynchronous="True"!!!
<ObjectDataProvider x:Key="PostDS" IsAsynchronous="True" ObjectType="{x:Type local:PostDB}" />

Mike_BB Oct 29, 2008 at 8:41 AM 
How too with Entity Framework datasource? If I create class
public class PostDB:List<Post>
{

public PostDB()
{
PostEntities db = new PostEntities();
this.AddRange(this.AddRange((from d in db.Post
select d).ToList<Post>());
}
}
In Runtime OK? but in Design Time - error "Could not create an instance of type 'PostDB"