如何将自定义数据与CollectionViewGroup关联?

时间:2012-11-05 15:23:41

标签: wpf collectionviewsource icollectionview

我在XAML中有一个ItemsControl,我为每个组显示一个扩展器,这样我就可以扩展/折叠组。我想要保持IsExpanded属性的状态(以及可能与组头的显示有关的其他设置)。通常你只有一个包含属性的类并绑定到它。但是,该组的数据上下文为CollectionViewGroup。现在这个类不是很有帮助,因为它只给你Name属性和组中的项目(如果你只是想要一个标题,这可能很好,并且可能根据组中的项目数量或它们显示某种度量标准内容但不是,如果您只想存储有关组头UI状态的自定义数据)。我想要做的是从这个类派生并将其他属性添加到我的派生类并绑定到它。但似乎没有任何简单的方法可以做到这一点。小组生成的所有细节似乎都隐藏在内部课程中,这非常令人沮丧。有没有人沿着实现ICollectionView的路线走下去(因此大概是所有其他相关的类)?复制ListCollectionView中的所有内容似乎是一项巨大的工作,只是为了能够创建自定义CollectionViewGroup类并将其绑定到该类!感谢。

3 个答案:

答案 0 :(得分:1)

一种方法是使用MultiBinding来查找或计算自定义数据和绑定时间。

我创建了一个DataGrid组,在标题中显示了组中特定值项的总和,以便在组项更改时更新此总和我使用自定义多值转换器进行多值绑定,即多值绑定ItemCount属性允许在组项更改时收到通知,然后更新总和并显示新闻值。

以下是多值转换器类的代码:

Public Class UserBalanceConverter
Implements IMultiValueConverter

Private Function GetSubTotal(ByVal obj As CollectionViewGroup) As String

    Dim total As Decimal
    For Each objItem As Object In obj.Items
        If TypeOf objItem Is Account Then
            Dim a As Account = DirectCast(objItem, Account)
            Dim rate As Decimal = 1
            rate = 1 / ExchangeRatesInfo.GetExchangeRate(a.currencyCode.ToString)

            total += a.Balance * rate
        Else
            total += GetSubTotal(objItem)
        End If
    Next

    Return total.ToString("C")
End Function

Public Function Convert(ByVal value() As Object,
                        ByVal targetType As System.Type,
                        ByVal parameter As Object,
                        ByVal culture As System.Globalization.CultureInfo) _
         As Object Implements System.Windows.Data.IMultiValueConverter.Convert

    Dim cvg As CollectionViewGroup = CType(value(1), CollectionViewGroup)

    Return GetSubTotal(cvg)

End Function


Public Function ConvertBack(ByVal value As Object,
                            ByVal targetType() As System.Type,
                            ByVal parameter As Object,
                            ByVal culture As System.Globalization.CultureInfo) _
        As Object() Implements System.Windows.Data.IMultiValueConverter.ConvertBack

    Throw New NotImplementedException

End Function

End Class

然后在XAML中,您使用用于GroupItem的样式的多值转换器:

  <Style TargetType ="{x:Type GroupItem}" x:Key="UserGroupHeaderStyle">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type GroupItem}">
                        <Expander x:Name="exp" IsExpanded="False">
                            <Expander.Header>
                                <StackPanel >
                                    <TextBlock Text="{Binding Name}" />
                                    <StackPanel Orientation="Horizontal" >
                                        <TextBlock Text="{Binding ItemCount}">
                                        <TextBlock Text=" "/>
                                        <TextBlock Text="items" />
                                        <TextBlock Text=" "/>
                                        <TextBlock Text="Balance: " />
                                        <TextBlock>
                                            <TextBlock.Text>
                                                <MultiBinding Converter="{StaticResource UserBalanceConverter}">
                                                    <Binding Path="ItemCount"/>
                                                    <Binding />
                                                </MultiBinding>
                                            </TextBlock.Text>
                                        </TextBlock>
                                    </StackPanel>
                                </StackPanel>
                            </Expander.Header>
                            <ItemsPresenter />
                        </Expander>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

完成将样式应用于DataGrid:

<DataGrid.GroupStyle>
     <GroupStyle ContainerStyle="{StaticResource UserGroupHeaderStyle}">
             <GroupStyle.Panel>
                   <ItemsPanelTemplate>
                           <DataGridRowsPresenter/>
                   </ItemsPanelTemplate>
             </GroupStyle.Panel>
     </GroupStyle>
 </DataGrid.GroupStyle>

另外,不要忘记在XAML的资源部分声明您的转换类:

  <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
             <local:UserBalanceConverter x:Key="UserBalanceConverter"/>
        </ResourceDictionary.MergedDictionaries>
  </ResourceDictionary>

EtVoilà!它就像一个魅力!

HTH

答案 1 :(得分:0)

一种简单的方法是将CollectionViewGroup包装到另一个ViewModel类中,该类提供额外需要的显示属性,如IsExpanded。课程我学到了很难的方法是不要弯曲xaml / view以匹配业务数据。而是弯曲/包装或转换业务数据以匹配UI的要求。

答案 2 :(得分:0)

我能够使用一种类似于Cédric建议的方法来解决正是这个问题(即绑定到IsExpanded),但是看似更加MVVM方式:

<ControlTemplate TargetType="GroupItem">
    <TreeViewItem IsExpanded="{Binding Items[0].IsGroupExpanded, Mode=TwoWay}">
        <TreeViewItem.Header>
            <TextBlock Text="{Binding Name}" />
        </TreeViewItem.Header>
        <TreeViewItem.Items>
            <ItemsPresenter />
        </TreeViewItem.Items>
    </TreeViewItem>
</ControlTemplate>

ItemViewModel.IsGroupExpanded setter和getter都重定向到Group.IsExpanded

请注意,必须指定Mode=TwoWay,因为默认情况下IsExpanded似乎绑定了OneWay