【问题标题】:Sorting grouped ListView which contains expanders对包含扩展器的分组 ListView 进行排序
【发布时间】:2012-12-02 20:51:38
【问题描述】:

我正在使用流行的代码对列表视图项进行排序和分组。排序和分组工作完美。问题是当用户单击列标题进行排序时,所有组都变成即展开或折叠(这取决于 Expander IsExpanded="False") 我需要的是对列进行排序,使展开器处于当前状态:一些展开,一些折叠.我还检查了一些示例项目,但它们都有相同的行为。有什么想法,可行吗?提前致谢!

<ListView.GroupStyle>
                                <GroupStyle>
                                    <GroupStyle.ContainerStyle>
                                        <Style TargetType="{x:Type GroupItem}">
                                            <Setter Property="Margin" Value="0,0,0,5"/>
                                            <Setter Property="Template">
                                                <Setter.Value>
                                                    <ControlTemplate TargetType="{x:Type GroupItem}">
                                                        <Expander IsExpanded="False" BorderBrush="#FFA4B97F" 
                                  BorderThickness="0,0,0,1" >
                                                            <Expander.Header>
                                                                <DockPanel>
                                                                    <TextBlock FontWeight="Bold" Text="{Binding Path=Name}" 
                                 Margin="5,0" Width="Auto"/>
                                                                    <TextBlock FontWeight="Bold" 
                                 Text="{Binding Path=ItemCount}"/>
                                                                    <TextBlock FontWeight="Bold" Text=" Items"/>
                                                                </DockPanel>
                                                            </Expander.Header>
                                                            <Expander.Content>
                                                                <ItemsPresenter />
                                                            </Expander.Content>
                                                        </Expander>
                                                    </ControlTemplate>
                                                </Setter.Value>
                                            </Setter>
                                        </Style>
                                    </GroupStyle.ContainerStyle>
                                </GroupStyle>
                            </ListView.GroupStyle>

ICollectionView view = CollectionViewSource.GetDefaultView(dataSet.Tables[0]);
                view.GroupDescriptions.Add(new PropertyGroupDescription("NameOfColumnForGrouping"));
                listViewOpportunitiesHistory.ItemsSource = view;

排序:

listViewOpportunitiesHistory.Items.SortDescriptions.Add(new SortDescription(field, newDir));

这是我解决问题的方法:

<ListView  x:Name="listViewOpportunitiesHistory" ItemsSource="{Binding}" AlternationCount="2" 
                              IsTextSearchEnabled="False" IsSynchronizedWithCurrentItem="True"   >
            <ListView.GroupStyle>
                <GroupStyle>
                    <GroupStyle.ContainerStyle>
                        <Style TargetType="{x:Type GroupItem}">
                            <Setter Property="Margin" Value="0,0,0,5"/>
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type GroupItem}">
                                        <Grid x:Name="grid_ControlTemplate_listViewOpportunitiesHistory"  Loaded="grid_ControlTemplate_listViewOpportunitiesHistory_Loaded">
                                            <Expander  BorderBrush="#FFA4B97F" BorderThickness="0,0,0,1"  
                                                                   x:Name="expanderControlTemplate" Expanded="expanderExpandCollapse_Expanded" Collapsed="expanderExpandCollapse_Collapsed" >
                                                <Expander.Header>
                                                    <DockPanel>
                                                        <TextBlock FontWeight="Bold" Text="{Binding Path=Name}" 
                                 Margin="5,0" Width="Auto"/>
                                                        <TextBlock FontWeight="Bold" 
                                 Text="{Binding Path=ItemCount}"/>
                                                        <TextBlock FontWeight="Bold" Text=" Items"/>
                                                    </DockPanel>
                                                </Expander.Header>
                                                <Expander.Content>
                                                    <ItemsPresenter />
                                                </Expander.Content>
                                            </Expander>
                                        </Grid>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </GroupStyle.ContainerStyle>
                </GroupStyle>
            </ListView.GroupStyle>
            <ListView.View>
                <GridView>
                    <GridView.Columns>      
                       <GridViewColumn Width="Auto" x:Name="listViewOpportunitiesHistoryColumn_Time"  >
                            <GridViewColumnHeader Click="SortClickHistory" Tag="Time"  Content=" Time "  x:Name="listViewOpportunitiesHistoryColumnHeader_Time"  />
                            <GridViewColumn.CellTemplate >
                                <DataTemplate>
                                    <Border BorderBrush ="Gray" BorderThickness="0,0,1,0" Margin="-6,0,-6,0">
                                        <Grid Margin="6,0,6,0" >
                                            <TextBlock Text="{Binding Path=Time, StringFormat='yyyy-MM-dd HH:mm:ss.fff'}" Grid.Column ="0" TextTrimming="CharacterEllipsis" VerticalAlignment="Center" HorizontalAlignment="Left" ToolTipService.ToolTip="{Binding Path=Time}" />
                                        </Grid>
                                    </Border>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                       <GridViewColumn Width="Auto" x:Name="listViewOpportunitiesHistoryColumn_AOValue"  >
                            <GridViewColumnHeader Click="SortClickHistory" Tag="AOValue"  Content=" AO Value "  x:Name="listViewOpportunitiesHistoryColumnHeader_AOValue"  />
                            <GridViewColumn.CellTemplate >
                                <DataTemplate>
                                    <Border BorderBrush ="Gray" BorderThickness="0,0,1,0" Margin="-6,0,-6,0">
                                        <Grid Margin="6,0,6,0" >
                                            <TextBlock Text="{Binding Path=AOValue}" Grid.Column ="0" TextTrimming="CharacterEllipsis" VerticalAlignment="Center" HorizontalAlignment="Left" ToolTipService.ToolTip="{Binding Path=AOValue}" />
                                        </Grid>
                                    </Border>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>       
                    </GridView.Columns>
                </GridView>
            </ListView.View>  
        </ListView>

后面的代码:

private Dictionary<string, bool?> expandStates = new Dictionary<string, bool?>();
        private void grid_ControlTemplate_listViewOpportunitiesHistory_Loaded(object sender, RoutedEventArgs e)
        {
            var grid = (Grid)sender;
            var dc = grid.DataContext as CollectionViewGroup;
            var groupName = (string)dc.Name.ToString();

            //If the dictionary contains the current group, retrieve a saved state of the group
            if (this.expandStates.ContainsKey(groupName))
            {
                var expander = (Expander)grid.FindName("expanderControlTemplate");
                //btn.IsExpanded = this.expandStates[groupName];
                if (this.expandStates[groupName] == true)
                {
                    expander.IsExpanded = true;
                }
                if (this.expandStates[groupName] == false)
                {
                    expander.IsExpanded = false;
                }

            }     
        }     
        private void expanderExpandCollapse_Collapsed(object sender, RoutedEventArgs e)
        {
            var expander = (Expander)sender;
            var dc = (CollectionViewGroup)expander.DataContext;
            var groupName = (string)dc.Name.ToString();

            //Loaded event is fired earlier than the Click event, so I'm sure that the dictionary contains the key
            this.expandStates[groupName] = expander.IsExpanded; //Save the current state
        }
        private void expanderExpandCollapse_Expanded(object sender, RoutedEventArgs e)
        {
            var expander = (Expander)sender;
            var dc = (CollectionViewGroup)expander.DataContext;
            var groupName = (string)dc.Name.ToString();

            //Loaded event is fired earlier than the Click event, so I'm sure that the dictionary contains the key
            this.expandStates[groupName] = expander.IsExpanded; //Save the current state
        }

我从 DataSet 中获取数据:

ICollectionView view = CollectionViewSource.GetDefaultView(dataSet.Tables[0]); 
 view.GroupDescriptions.Add(new PropertyGroupDescription(FXH.string_GroupBy_OpportunitiesHistory));
 listViewOpportunitiesHistory.ItemsSource = view;

此方案基于Sort and Group ListItems in a WPF ListBox- GroupItem collapse and expand

【问题讨论】:

    标签: c# wpf listview


    【解决方案1】:

    如果您希望每个组的扩展器保存其 IsExpanded 属性,则必须使用数据绑定,或者您必须对 View (扩展器本身)进行排序.我认为第一种方法很容易实现。您需要 bool 值的镜像集合用于组集合。在 xaml 中,你应该绑定转换器:

    <Expander IsExpanded="{Binding Converter={StaticResource MyOwnConverter}}" 
              BorderBrush="#FFA4B97F" 
              BorderThickness="0,0,0,1" >
        <Expander.Header>
            <DockPanel>
                <TextBlock FontWeight="Bold" Text="{Binding Path=Name}" 
                           Margin="5,0" Width="Auto"/>
                <TextBlock FontWeight="Bold" 
                           Text="{Binding Path=ItemCount}"/>
                <TextBlock FontWeight="Bold" Text=" Items"/>
            </DockPanel>
        </Expander.Header>
        <Expander.Content>
            <ItemsPresenter />
        </Expander.Content>
    </Expander>
    

    在转换器内部,您可以存储对 ViewModel 的引用(或仅存储到 ICollectionView),并存储每个组的当前 IsExpanded 状态并将其用于知道要返回哪个值。您还应该小心处理 CollectionChanged 事件(如果您的集合在运行时发生更改),以添加或删除组的状态。

    【讨论】:

    • 感谢 stukselbax,我试过但不知道如何使用转换器对其进行排序。使用你的方法可能比我目前使用的更优雅。如果您能提供一些更详细的代码,我将不胜感激。
    猜你喜欢
    • 1970-01-01
    • 2010-09-18
    • 1970-01-01
    • 2010-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-03
    相关资源
    最近更新 更多