开发者

C#/XAML/WPF binding working partially, only displays first item in List

开发者 https://www.devze.com 2023-02-12 10:06 出处:网络
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

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>


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.


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.


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>
0

精彩评论

暂无评论...
验证码 换一张
取 消