Tôi đã có một ItemsControl trong XAML nơi tôi đang hiển thị một expander cho mỗi nhóm vì vậy tôi có thể mở rộng/thu gọn nhóm. Tôi muốn duy trì trạng thái của thuộc tính IsExpanded
(và các cài đặt khác có khả năng liên quan đến việc hiển thị tiêu đề nhóm). Thông thường bạn chỉ có một lớp với các thuộc tính trên nó và liên kết với điều này. Tuy nhiên, ngữ cảnh dữ liệu cho nhóm là CollectionViewGroup
. Bây giờ lớp này không hữu ích vì nó chỉ cung cấp cho bạn thuộc tính Tên và các mục trong nhóm (điều này là tốt nếu bạn chỉ muốn một tiêu đề và có thể hiển thị một số loại chỉ số dựa trên số lượng các mục trong nhóm hoặc của chúng nội dung nhưng không phải nếu bạn chỉ muốn lưu trữ dữ liệu tùy chỉnh về trạng thái của giao diện người dùng tiêu đề nhóm). Những gì tôi muốn làm là lấy được từ lớp này và thêm các thuộc tính khác vào lớp dẫn xuất của tôi và liên kết với nó thay vào đó. Nhưng dường như không có cách nào dễ dàng để làm điều này. Tất cả các chi tiết của thế hệ nhóm dường như được ẩn đi trong các lớp học nội bộ mà rất bực bội. Có ai đi xuống con đường thực hiện ICollectionView
mình (và do đó tất cả các lớp liên quan khác cũng có lẽ)? Nó có vẻ giống như một công việc lớn để nhân rộng mọi thứ trong ListCollectionView
chỉ để có thể tạo ra một lớp tùy chỉnh CollectionViewGroup
và liên kết với điều đó thay thế! Cảm ơn.Làm cách nào để liên kết dữ liệu tùy chỉnh với một CollectionViewGroup?
Trả lời
Một cách tiếp cận đơn giản là chỉ cần quấn CollectionViewGroup vào một lớp ViewModel khác để cung cấp các thuộc tính hiển thị cần thiết bổ sung như IsExpanded. Một bài học tôi đã học được một cách khó khăn là không uốn cong xaml/view để phù hợp với dữ liệu kinh doanh. Thay vào đó hãy uốn cong/quấn hoặc chuyển đổi dữ liệu nghiệp vụ để phù hợp với các yêu cầu của giao diện người dùng.
Một cách tiếp cận là sử dụng MultiBinding
để tìm hoặc tính toán dữ liệu tùy chỉnh và thời gian liên kết.
tôi đã thực hiện một DataGrid
với nhóm cho thấy trong phần đầu tổng các mặt hàng giá trị cụ thể trong nhóm, để cập nhật số tiền này khi mục nhóm thay đổi tôi đã thực hiện một multivalue ràng buộc với một bộ chuyển đổi tùy chỉnh multivalue, các multivalue ràng buộc với ItemCount
tài sản cho phép để được thông báo khi nhóm thay đổi và sau đó cập nhật số tiền và hiển thị giá trị newsum.
Đây là mã cho lớp chuyển đổi multivalue:
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
Sau đó, trong XAML bạn sử dụng bộ chuyển đổi multivalue trong một phong cách sử dụng cho 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>
Kết thúc với việc áp dụng các phong cách để bạn DataGrid:
<DataGrid.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource UserGroupHeaderStyle}">
<GroupStyle.Panel>
<ItemsPanelTemplate>
<DataGridRowsPresenter/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</DataGrid.GroupStyle>
Cũng đừng quên khai báo lớp chuyển đổi của bạn n phần tài nguyên của XAML của bạn:
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<local:UserBalanceConverter x:Key="UserBalanceConverter"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Et Voilà! Nó hoạt động như một say mê!
HTH
cách này trả lời câu hỏi của OP? anh ta hỏi làm thế nào để duy trì giá trị IsExpanded và không tạo ra các số liệu từ các mục mà anh ta đã loại trừ trong câu hỏi. – Firo
tôi đã có thể giải quyết chính xác vấn đề này (tức là ràng buộc để IsExpanded
) sử dụng một cách tiếp cận đó là hơi tương tự như đề nghị Cédric, nhưng trong một MVVM cách dường như hơn:
<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>
Cả hai ItemViewModel.IsGroupExpanded
setter và getter chuyển hướng đến Group.IsExpanded
.
Lưu ý rằng Mode=TwoWay
phải được chỉ định, vì IsExpanded
dường như bị ràng buộc OneWay
theo mặc định.
Bạn có thể giải thích quan điểm của mình bằng ví dụ không? –