【问题标题】:C#/XAML/WPF binding working partially, only displays first item in ListC#/XAML/WPF 绑定部分工作,仅显示列表中的第一项
【发布时间】:2011-06-29 22:38:40
【问题描述】:

我有一个非常简单的绑定,但我看到的问题是,我看到的不是显示三个公司(company_list 是一个列表,其中 Company 包含要绑定的 company_id),而是弹出窗口company_list 中只有 first company_id。我有其他似乎工作正常的绑定,在其他一些情况下,我看到我使用了 ItemSource 而不是 DataContext,但是当我使用它时,我得到“使用 ItemsSource 之前项目集合必须为空”。我在 stackoverflow、msdn 和其他地方广泛搜索了这个问题的简单答案,并且看到了大多数我无法理解/应用的非常复杂的解决方案。

当我的窗口出现时,它有:

A公司

它应该在哪里:

A公司
公司B
公司C

这是 company_list 的内容(是的,在调试器中验证)。建议赞赏!代码和 XAML 紧随其后。

    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();

还有来自 CompanySelect 的 XAML:

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

【问题讨论】:

    标签: c# wpf binding


    【解决方案1】:

    问题是,您在 XAML 代码中定义了一个 ListViewItem。你不应该这样做。
    试试这样的:

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

    【讨论】:

      【解决方案2】:

      首先,只在cs_window.Show()之后设置DataContext。

      其次,您小时候在 ListView 的 XAML 中拥有的 ListViewItem 是您只看到一个的原因。

      第三,如果您在 XAML 中定义 ItemsSource,可能会更好(并且会更类似于 MVVM),如下所示:

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

      这是在将 a_state 设置为 ListView 的容器或其他祖先元素的 DataContext 之后。

      【讨论】:

      • 我能够按照建议在 cs_window.Show() 之后设置 ItemSource。凉爽的!我将按照建议在 XAML 中尝试 ItemsSource;以前尝试过,但当时也有其他问题:-)
      【解决方案3】:

      我会在代码隐藏中设置 ListView 的 ItemsSource,而不是 DataContext:

      cs_window.CompanyListView.ItemsSource = a_state.company_list;
      

      或绑定:

      <ListView ItemsSource="{Binding company_list}">
      

      然后改为设置ListView的ItemTemplate。

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

      我还会考虑使用 MVVM design pattern 来实现可测试性和关注点分离,并考虑使用 PascalCase 作为您的属性名称。

      另外,除非您特别想要 ListView,否则我会使用 ListBox。

      【讨论】:

      • 谢谢,这有帮助。请注意,“TextBlock”似乎没有 Content 属性,它是 Text="{Binding company_id}"。
      • 另外,您为什么建议使用 ListBox 与 ListView?我遇到的一个问题是,既然我的 ListView 出现了所有 3 家公司,第一个被自动选择了 - 我想显示这些公司,默认情况下没有选择它们。
      • 您可以根据需要设置 SelectedItem 属性。 ListView/ListBox 的区别见stackoverflow.com/questions/227231/…
      猜你喜欢
      • 2013-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-22
      • 2014-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多