【问题标题】:Binding collection to ComboBox in Listview将集合绑定到 Listview 中的 ComboBox
【发布时间】:2013-04-28 22:45:58
【问题描述】:

我有一个ListView,它的DataTemplate 由一个ComboBox 和一些TextBoxes 组成。 ComboBox 绑定到映射到 CollectionViewSource 的 Collection。 ListView 可以有任意数量的行。

问题是在ComboBox 中选择一个项目会改变它们。我确实希望它们都填充相同的内容,但能够独立设置。

资源部分包含以下内容:

    <CollectionViewSource Source="{Binding ChildAccounts}" x:Key="ChildGroupedData">
        <CollectionViewSource.GroupDescriptions>
            <PropertyGroupDescription PropertyName="group"/>
        </CollectionViewSource.GroupDescriptions>
    </CollectionViewSource>

    <!-- Template for each child item in ListView -->
    <DataTemplate x:Key="ChildTemplate">
        <Grid>
            <Grid.ColumnDefinitions>                    
                <ColumnDefinition Width="90"/>
                <ColumnDefinition Width="130"/>
                <ColumnDefinition Width="90"/>
                <ColumnDefinition Width="90"/>
                <ColumnDefinition Width="90"/>
                <ColumnDefinition Width="210"/>
            </Grid.ColumnDefinitions>                
            <Label Grid.Column="0" Content="Account" HorizontalAlignment="Left" VerticalAlignment="Top" Foreground="{StaticResource CustomWhite}" FontSize="14" Width="80"/>
            <ComboBox Grid.Column="1" SelectedValue="{Binding Path=accFrom}" ItemsSource="{Binding Source={StaticResource ChildGroupedData}}" ItemTemplate="{StaticResource AccountTemplate}" SelectedValuePath="ID" Width="120" Style="{StaticResource RoundedComboBox}" HorizontalAlignment="Left" VerticalAlignment="Center">
                <ComboBox.GroupStyle>
                    <GroupStyle ContainerStyle="{StaticResource CustomExpanderComboGroupItemStyle}" HeaderTemplate="{StaticResource GroupHeader}"/>
                </ComboBox.GroupStyle>
            </ComboBox>
            <Label Grid.Column="2" Content="Amount" HorizontalAlignment="Left" VerticalAlignment="Top" Foreground="{StaticResource CustomWhite}" FontSize="14" Width="80"/>
            <TextBox Grid.Column="3" Text="{Binding Path=amount, StringFormat='#,##0.00'}" Style="{StaticResource RoundedTextBox}" Width="80" HorizontalAlignment="Left" VerticalAlignment="Center"/>
            <Label Grid.Column="4" Content="Comment" HorizontalAlignment="Left" VerticalAlignment="Top" Foreground="{StaticResource CustomWhite}" FontSize="14" Width="80"/>
            <TextBox Grid.Column="5" Text="{Binding Path=comment}" Style="{StaticResource RoundedTextBox}" Width="200" HorizontalAlignment="Left" VerticalAlignment="Center"/>
        </Grid>
    </DataTemplate>

    <!-- ListView template -->
    <Style x:Key="ChildListViewStyle" TargetType="{x:Type ListView}">
        <Setter Property="ItemTemplate" Value="{DynamicResource ChildTemplate}"/>
        <Setter Property="Background" Value="{StaticResource CustomBackground}"/>
        <Setter Property="BorderThickness" Value="0"/>
        <Setter Property="HorizontalAlignment" Value="Left"/>
        <Setter Property="Margin" Value="10,10,10,10"/>
        <Setter Property="VerticalAlignment" Value="Top"/>
        <Setter Property="Padding" Value="0,0,50,0"/>
        <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
        <Style.Resources>
            <!-- Makes selection invisible when focus lost -->
            <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="{StaticResource CustomBackgroundC}"/>
        </Style.Resources>
    </Style>

ListView 定义为:

<ListView Grid.Column="0" x:Name="lstChildren" Margin="20,30,0,0" ItemsSource="{Binding Path=Items}" Style="{StaticResource ChildListViewStyle}"/>

编辑:

在关联类中找到以下内容

Imports System.Data
Imports System.Data.OleDb
Imports System.Collections.ObjectModel
Imports System.ComponentModel

Class ItemView
Implements INotifyPropertyChanged

Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

Private Sub NotifyPropertyChanged(ByVal info As String)
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
End Sub

....

Private _ChildAccounts As ObservableCollection(Of AccountEntry)
Public Property ChildAccounts As ObservableCollection(Of AccountEntry)
    Get
        Return _ChildAccounts
    End Get
    Set(value As ObservableCollection(Of AccountEntry))
        _ChildAccounts = value
    End Set
End Property

....

Private Sub ItemView_Initialized(sender As Object, e As EventArgs) Handles Me.Initialized

    Dim dsacmd As OleDbDataAdapter
    Dim dsa As New DataSet
    Dim dva As DataView
    Dim strSelect As String

    Try
        ' ** Open a connection to the database.        
        cn = New OleDbConnection(strConnection)
        cn.Open()

        Me.DataContext = Me

        strSelect = "SELECT Accounts.ID, Accounts.deleted, Accounts.accType, Accounts.currency as curr, IIf([Currencies.ID]=1,Accounts.comment,Accounts.comment & "" ("" & Currencies.symbol & "")"") AS comment, Currencies.comment AS currS FROM Currencies INNER JOIN Accounts ON Currencies.ID = Accounts.currency"
        dsacmd = New OleDbDataAdapter(strSelect, cn)
        dsacmd.Fill(dsa, "Accounts")
        dva = New DataView(dsa.Tables("Accounts"))
        dva.RowFilter = "accType=" & cVirtual.ToString & " AND deleted=False"
        dva.Sort = "curr, comment"
        ChildAccounts = New ObservableCollection(Of AccountEntry)(dva.ToTable.AsEnumerable().[Select](Function(i) New [AccountEntry](i("ID"), i("currS").TrimEnd(" "), i("comment"))))

....

Private Sub DisplayItem()

    ....

            strSelect = ""
            Dim Relations As Collection(Of Relation) = GetRelations(ID)
            For Each r As Relation In Relations
                strSelect &= "ID=" & r.ID.ToString & " OR "
            Next
            If strSelect <> "" Then strSelect = "SELECT * FROM Items WHERE " & strSelect.Substring(0, strSelect.Length - 4)
            If strSelect <> "" Then
                dsrcmd = New OleDbDataAdapter(strSelect, cn)
                dsr.Clear()
                dsrcmd.Fill(dsr, "Items")
                lstChildren.DataContext = dsr
            End If
....

【问题讨论】:

    标签: wpf xaml listview collections combobox


    【解决方案1】:

    您需要将您的CollectionViewSource 移动到DataTemplate。要强制所有组合框项目使用相同的源集合,我认为您可以尝试两件事:

    一个 - 使用相对源从ListViewDataContext 中选择ChildAccounts

    ...
    <Grid.Resources>
      <CollectionViewSource x:Key="ChildGroupedData"
                            Source="{Binding RelativeSource={RelativeSource FindAncestor,
                                                                            AncestorType={x:Type ListView}},
                                              Path=DataContext.ChildAccounts}">
        <CollectionViewSource.GroupDescriptions>
          <PropertyGroupDescription PropertyName="group" />
        </CollectionViewSource.GroupDescriptions>
      </CollectionViewSource>
    </Grid.Resources>
    ...
    

    更新:

    上面的方法可以在我整理的This示例中看到。请注意,ChildAccount 只是视图模型中的一个 ObservableCollection&lt;T&gt;,这样我们就不会为每个 ListBoxItem 提供一个新集合,而是像您在问题中要求的那样共享它们。

    如果您的 ChildAccounts 属性实际上类似于“注释”属性,其中每个 ListBoxItem 都有一个 ChildAccounts 属性对象,只需更改

    <CollectionViewSource x:Key="ChildGroupedData"
                            Source="{Binding RelativeSource={RelativeSource FindAncestor,
                                                                            AncestorType={x:Type ListView}},
                                              Path=DataContext.ChildAccounts}">
    

    <CollectionViewSource x:Key="ChildGroupedData"
                            Source="{Binding ChildAccounts}">
    

    它也应该可以工作。但是,您现在确实拥有每个 ListBoxItem 的 ChildAccounts 集合,并且没有共享其来源。

    主要是在DataTemplate 中定义CollectionViewSource。下载随附的示例并亲自尝试并检查具体细节。

    两个 - 将ChildAccounts 作为静态变量

    ...
    <Grid.Resources>
      <CollectionViewSource x:Key="ChildGroupedData"
                            Source="{x:Static local:ChildAccounts}">
        <CollectionViewSource.GroupDescriptions>
          <PropertyGroupDescription PropertyName="group" />
        </CollectionViewSource.GroupDescriptions>
      </CollectionViewSource>
    </Grid.Resources>
    ...
    

    【讨论】:

    • 谢谢。尝试了第一个,它不起作用。组合框是空的。无法获得第二个编译。它说“在目标类型上找不到成员 'ChildAccounts'”和“l:ChildAccounts 成员无效,因为它没有合格的类型名称。我将其更改为 {x:Static l:ItemView.ChildAccounts} - 然后只会出现一个错误 - 在“ItemView”类型上找不到成员“ChildAccounts”。我已声明 xmlns:l="clr-namespace:WpfAccounts" 以允许访问命名空间。代码中包含 ChildAccounts 的类称为 ItemView。谢谢。安迪
    • @AndyPowell 第一种方法对我来说效果很好。您能否为 ChuldAccounts 属性和 Items 属性发布您的视图模型代码。如果需要,修剪代码。保留命名空间和类结构。我也会将我的工作解决方案发布到 Dropbox,以便您稍后尝试。绑定到 ListView 的属性 Items 是 ItemView 类对象的可观察集合吗?
    • @AndyPowell 我在选项 1 之后更新了我的答案,其中包含一个下载示例项目的链接,该示例项目显示选项 1 正常工作。下载并查看您的 VM 属性声明有何不同。我在答案中提到的选项 2 是针对静态变量的。如果你的属性不是静态的,你就不能使用它。
    • 谢谢。今晚会看。我不认为我正在使用 ViewModel (但肯定会从你的例子中学习)。 ChildAccounts 在类 ItemView 中被声明为 ObservableCollection(Of Account) 的公共属性。今晚将用代码更新问题。
    • 我想我可能已经破解了.....&lt;CollectionViewSource x:Key="ChildData" Source="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.ChildAccounts}"&gt; 我认为有效!
    【解决方案2】:

    您可以将集 IsSynchronizedWithCurrentItem="False" 添加到组合框。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-31
      • 2010-09-17
      • 2018-08-02
      • 1970-01-01
      • 2016-06-17
      • 2013-03-22
      • 2010-12-21
      相关资源
      最近更新 更多