ListBox ItemsSource WPF Binding

user2013535 picture user2013535 · Mar 16, 2014 · Viewed 49.3k times · Source

I'm not understanding something about binding. I have a DataTemplate for type Object which is working, but in there I want to make another ListBox and set the data to that of one of the properties of an Object. I've been using Snoop to look at the data context and the data context of the ListBox in the Object DataTemplate is an Object, but there is an error with the ItemsSource and I don't know why. I'm doing ItemsSource={Binding componentList, Mode=TwoWay} and an Object has a componentList and componentList is an ObservableList. What am I missing?

Here's my XAML code:

<Window.Resources>

<DataTemplate DataType="{x:Type properties:Component}">
  <StackPanel>
    <TextBlock Text="TEST COMPONENT" />
    <ListBox DataContext="{Binding propertyList}" ItemsSource="{Binding propertyList}" />
  </StackPanel>
</DataTemplate>

<DataTemplate DataType="{x:Type properties:Object}">
  <StackPanel>
    <TextBlock Text="TEST OBJECT" />
    <ListBox ItemsSource="{Binding componentList, Mode=TwoWay}" />
  </StackPanel>
</DataTemplate>

</Window.Resources>

And my C# code:

public class Component
{
  public string name;
  public ObservableCollection<IProperty> propertyList;
}

public class Object
{
  public UnsignedProperty objectID;
  public ObservableCollection<Component> componentList;
}

I make a ListBox in code and set it's ItemsSource to a list of Objects and that's seeing my Object DataTemplate, but that's where it stops

ListBox properties = new ListBox();
ObservableCollection<Properties.Object> t = new ObservableCollection<Properties.Object>();
t.Add(selectedObject); //potentially more objects
properties.ItemsSource = t;
PropertyPane.Content = properties;

any help would be much appreciated. Thanks!

Answer

eran otzap picture eran otzap · Mar 17, 2014

In addition to my comments above:

You don't have to create a ListBox in code, create it in XAML and bind a collection to your ItemsSource (Dependency Property).

Like so:

C#:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;

        Components.Add(new Object());
        Components.Add(new Object());
    }

    private ObservableCollection<Object> components;
    public ObservableCollection<Object> Components
    {
        get
        {
            if (components == null)
                components = new ObservableCollection<Object>();
            return components;
        }
    }
}

XAML :

<Window>   
   <Grid>
      <ListBox  ItemsSource="{Binding Components, Mode=OneWay}" />        
   </Grid>        
</Window>

In addition here is a continuation of your code:

C#:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;

        ListBox properties = new ListBox();
        ObservableCollection<Object> t = new ObservableCollection<Object>();
        t.Add(new Object()); //potentially more objects
        properties.ItemsSource = t;
        PropertyPane.Content = properties;
    }        
}

public interface IProperty
{
}

public class Component
{
    public string name;

    private ObservableCollection<IProperty> propertyList;
    public ObservableCollection<IProperty> PropertyList
    {
        get
        {
            if (propertyList == null)
                propertyList = new ObservableCollection<IProperty>();
            return propertyList;
        }
    }
}

public class Object
{
    private ObservableCollection<Component> componentList;
    public ObservableCollection<Component> ComponentList 
    {
        get
        {
            if (componentList == null)
                componentList = new ObservableCollection<Component>();
            return componentList;
        }
    }
}

XAML:

      <DataTemplate DataType="{x:Type local:Component}">
          <StackPanel>
              <TextBlock Text="TEST COMPONENT" />
              <ListBox ItemsSource="{Binding PropertyList, Mode=OneWay}" />
          </StackPanel>
      </DataTemplate>

      <DataTemplate DataType="{x:Type local:Object}">
          <StackPanel>
              <TextBlock Text="TEST OBJECT" />
              <ListBox ItemsSource="{Binding ComponentList, Mode=OneWay}" />
          </StackPanel>
      </DataTemplate>