2

I have what should be a really simple binding, but the problem I'm seeing is that instead of displaying the three companies (company_list is a List, where Company contains a company_id to bind to), I see the window pop up with only the first company_id in company_list. I have other bindings which seem to work fine, and in some other cases I see that I've used ItemSource instead of DataContext, but when I use that I get "Items collection must be empty before using ItemsSource". I've searched extensively for a simple answer to this in stackoverflow, msdn and elsewhere, and have seen mostly really complex solutions that I haven't been able to understand/apply.

When my window appears, it has:

CompanyA

where it should have:

CompanyA
CompanyB
CompanyC

which is the content of the company_list (yes, verified in debugger). Suggestions appreciated! Code and XAML follow.

    ReadMasterCompanyList();  // populates a_state.company_list with 3 companies
    // display company list dialog
    CompanySelect cs_window = new CompanySelect();
    cs_window.CompanyListView.DataContext = a_state.company_list;
    // fails: cs_window.CompanyListView.ItemsSource = a_state.company_list;
    cs_window.Show();

And the XAML from CompanySelect:

<Grid>
    <ListView IsSynchronizedWithCurrentItem="True" 
      x:Name="CompanyListView"
       SelectionMode="Single" SelectionChanged="CompanyListView_SelectionChanged">
        <ListView.ItemContainerStyle>
            <Style TargetType="{x:Type ListViewItem}">
                <Setter Property="Height" Value="30"/>
            </Style>
        </ListView.ItemContainerStyle>
        <ListViewItem Content="{Binding Path=company_id}"></ListViewItem>
    </ListView>
</Grid>
Ken
  • 369
  • 3
  • 15

3 Answers3

2

I would set the ItemsSource of the ListView, rather than the DataContext, either in codebehind:

cs_window.CompanyListView.ItemsSource = a_state.company_list;

or with binding:

<ListView ItemsSource="{Binding company_list}">

And then set the ItemTemplate of the ListView instead.

...
<ListView.ItemTemplate>
  <DataTemplate>
    <TextBlock Text="{Binding company_id}" />
  </DataTemplate>
</ListView.ItemTemplate>
...

I would also look into using the MVVM design pattern for testability and separation of concerns, and look at using PascalCase for your property names.

Also, unless you specifically wanted a ListView, I would use a ListBox.

devdigital
  • 34,151
  • 9
  • 98
  • 120
  • Thanks, this helped. Just one note, a "TextBlock" doesn't seem to have Content property, it's Text="{Binding company_id}". – Ken Feb 18 '11 at 16:52
  • Also, why do you suggest the ListBox vs ListView? One problem I have is that now that my ListView comes up with all 3 companies, the first one is automatically selected - I want to display the companies, with none of them selected by default. – Ken Feb 18 '11 at 16:59
  • You can set the SelectedItem property as appropriate. For difference between ListView/ListBox, see http://stackoverflow.com/questions/227231/wpf-listbox-vs-listview-how-to-choose-for-data-binding – devdigital Feb 18 '11 at 17:33
0

The problem is, that you define one ListViewItem in your XAML code. You shouldn't do this.
Try something like this:

<Grid>
    <ListView IsSynchronizedWithCurrentItem="True" 
      x:Name="CompanyListView"
       SelectionMode="Single" SelectionChanged="CompanyListView_SelectionChanged">
        <ListView.ItemContainerStyle>
            <Style TargetType="{x:Type ListViewItem}">
                <Setter Property="Height" Value="30"/>
            </Style>
        </ListView.ItemContainerStyle>
        <ListView.ItemTemplate>
            <DataTemplate>
                <TextBlock Content={Binding Path=company_id}/>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>
Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
0

First, set the DataContext only after cs_window.Show().

Second, the ListViewItem you have as a child in your ListView's XAML is why you're only seeing one.

Third, might work better (and would be more MVVM-ish) if you define ItemsSource in the XAML, like this:

<ListView ItemsSource="{Binding Path=company_list}" ...>

That's after making a_state the DataContext of the ListView's container or some other ancestor element.

Chris Wenham
  • 23,679
  • 13
  • 59
  • 69
  • I was able to set the ItemSource AFTER the cs_window.Show() as suggested. Cool! I will try ItemsSource in the XAML as suggested; had tried it before, but there was something else wrong then as well :-) – Ken Feb 18 '11 at 16:55