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