2
votes

Update: I've updated the code based on your help so far, and still no luck. When the application loads the ListBox has no items. I assign junk values to Customers in the windows's contructor, and then am also trying to set the ListBox's DataContext as follows:

CustomerList.DataContext = Customers;

--- Original Question (with updated code) ---

I'm having trouble with databinding in a WPF project.

I have a class, Customer, as follows:

public class Customer
{
    public String Name { get; set; }    
    public String Email { get; set; }
}

In my XAML's code behind I have a collection of customers as follows:

public List<Customer> Customers { get; set; }

I'm trying to bind each customer to a ListBox with a ListItemTemplate displaying the customer's information (name/email) in TextBoxes along with a button which locks/unloacks the TextBoxes (sets the IsEnabled property to true or false).

What's the best way to go about this?

So far I've been tryingt he following with no success.

In the XAML I currently have the following (ignoring the toggle part for now, I'm just trying to get the collection itself to be listed.):

<Window.Resources>
    <CollectionViewSource x:Key="Customers" Source="{Binding Path=Customers, Mode=TwoWay}"/>
    <DataTemplate x:Key="Customer">
        <StackPanel Orientation="Horizontal">
            <TextBox Content="{Binding Name}" />
            <TextBox Content="{Binding Email}" />
        </StackPanel>
    </DataTemplate>
</Window.Resources>

<StackPanel>
    <ListBox ItemsSource="{Binding Source={StaticResource Customers}}"
             ItemTemplate="{StaticResource ResourceKey=Customer}"
             Name="CustomerList"
             Height="300" />
</StackPanel>
3
Is Customers a field or a property? For binding to work, it has to be a property. - svick
you have given the same key to your CollectionViewSource and your DataTemplate. Change the key to something unique for one of them. - Matt Ellen
@ChrisF, When I run the application no items are being displayed in the ListBox, so I am assuming the data binding is not working for some reasons. - evan
@svick, Customers is a property of the MainWindow.xaml.cs - evan
I do not think that you need to specify the DataContext of the List, it does not use it (because it specifies a source), instead the window should set to whatever object contains the Customers, because in the CollectionViewSource you only specify a path so the DataContext will be used as the base-source. If you are new to all of this read the articles on MSDN like the Data Binding Overview. - H.B.

3 Answers

1
votes

You need to change

ItemsSource="{Binding Source=Customers}"

to

ItemsSource="{Binding Source={StaticResource Customers}}" DataContext="{StaticResource Customers}"
1
votes

Code similar to the updated one works for me after changing

<TextBox Content="{Binding Name}" />

to

<TextBox Text="{Binding Name}" />

As TextBox doesn't have Content property(like a Label), the former refused to compile in VS.

Well, it is set to Text in definition:

[ContentPropertyAttribute("Text")]
public class TextBox : TextBoxBase, IAddChild

But I thought it is only used between the brackets(<TextBox>Like so</TextBox>)?

Could this be the source of the problem?

0
votes

Try setting the ItemsSource of your CustomerList as follows: ItemsSource="{Binding}". You've set the DataContext of the ListBox to the list of customers, you need to set the ItemsSource to the same collection, hence, the direct binding.

Another thing that you can do, in case you prefer to use the CollectionViewSource, is to set the DataContext of your window to the same class DataContext=this, because without this, the resource definition won't be able to locate the "Customers" collection that you defined in the code behind. If you do this, however, you don't need CustomerList.DataContext = Customers; because you're directly assigning the ItemsSource to a static resource, not relatively to the DataContext.

One more thing. I think you should give the CollectionViewSource and the corresponding collection in the code behind different names. This isn't going to cause a runtime issue, but it makes it hard to maintain the code ;)

Hope this helps :)