Sarah Vessels
Sarah Vessels

Reputation: 31660

WPF newbie - setting ItemsSource in XAML doesn't seem to work

I'm new to WPF and trying to figure out all this databinding stuff. When I do the following in my code, my ComboBox is populated when I run my application:

public NewForm()
{
    InitializeComponent();
    Product.ItemsSource = Products;
}

public List<string> Products
{
    get { return _productsComponents.Keys.ToList(); }
}

However, in my XAML when I have the following, the ComboBox has no content in it when I run my application:

<ComboBox Height="23" HorizontalAlignment="Left" Margin="138,116,0,0"
          Name="Product" VerticalAlignment="Top" Width="120"
          ItemsSource="{Binding Path=Products}"/>

Am I referencing something incorrectly? This tutorial was helpful but he never set ItemsSource in XAML, always in C#.

Upvotes: 1

Views: 3427

Answers (4)

Anderson Faria
Anderson Faria

Reputation: 31

Put DataContext="{Binding RelativeSource={RelativeSource Self}}" in window:

<Window x:Class="ListViewTest.Test2.ListViewTest"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   DataContext="{Binding RelativeSource={RelativeSource Self}}"

Upvotes: 3

myermian
myermian

Reputation: 32525

I'd suggest trying to limit myself to either keeping the binding setup in code or in XAML, not mixing them. In you're situation, you're setting the ItemsSource upon form creation AND in XAML. I'm not sure why?

Anyways, it seems that you're '_productsComponents' is a Dictionary by your code. So I'm going to use that to my advantage in a better code version:

CODE-BEHIND:

public partial class NewForm : Window
{
    private Dictionary<String, String> _productsComponents;
    public Products
    {
        get { return _productsComponents; }
        set { _productsComponents= value; }
    }

    public NewForm()
    {
        Products = new Dictionary<String, String>();
        //Do you're dictionary loading...

        InitializeComponent();

        DataContext = this;

        ProductCmbBox.ItemsSource = Products;
        ProductCmbBox.SelectedValuePath = "Key";
        ProductCmbBox.DisplayMemberPath = "Value"; //or "Key" if you want...
    }
}

<ComboBox x:Name="ProductCmbBox" ... />

I'd also look into: Dr. WPF's ObservableDictionary. It allows you to make sure that if the Dictionary items change that you're combobox (UI) will be able to observe that change accordingly (that is, if you remove/add a keyvaluepair from you're dictionary that you're combobox will show the correct list always).

Upvotes: 0

Jimmy Hoffa
Jimmy Hoffa

Reputation: 5967

Try Binding Source=Products

Path is generally an addenda on Source from how I've used it, it's for when you need to access a subproperty of the elements available in the source.

Here's an example of a ListBox I have filled with elements from an XDocument stored in the static resources. This might hopefully explain the relationship between Binding Source and Path. Root.Elements is the member path to a collection supine to the XDocument referenced in the Source. Don't use the {StaticResource Product} mechanism in yours as you don't have your collection in the app xaml, but rather the current class.

<ListBox Height="660" Name="ResponsesListBox" Width="240"
                      MouseDoubleClick="ResponsesListBox_MouseDoubleClick"
                      MouseLeftButtonDown="WindowMoveHandler"
                      ItemsSource="{Binding Source={StaticResource ResponsesXDocument}, Path=Root.Elements}"
                      ItemTemplate="{StaticResource ListBoxDataTemplate}" />

Also handy is this WPF Data Binding Cheat Sheet, I have found it quite helpful: http://www.nbdtech.com/Blog/archive/2009/02/02/wpf-xaml-data-binding-cheat-sheet.aspx

Upvotes: 0

Jay
Jay

Reputation: 57969

By default, you're actually binding not to the form itself, but to the object assigned to the DataContext property. This facilitates using a view model to manage all the data outside the codebehind files.

You can probably assign the form itself to the DataContext property in the constructor

DataContext = this;

You can also bind to the form in any of several ways. Here is one:

<Window x:Name="thisWindow" …
    <ComboBox ItemsSource="{Binding Path=Products, ElementName=thisWindow}"…

I don't think that Products needs to be a DependencyProperty here, but don't quote me on that, and as long as the collection is not subject to change, you don't need to worry about update notifications.

Upvotes: 3

Related Questions