7

ObservableCollection我的视图模型中有一个,我的视图中有一个CollectionViewSourceListBox

绑定ListBox到. 绑定到CollectionViewSource,对项目进行排序并将它们分组。我通过. _ _ 这一切都很好。CollectionViewSourceObservableCollectionIsLiveGroupingRequestedIsLiveSortingRequestedCollectionViewSourceListBox

问题与选择有关。如果我在 中选择一个项目,ListBox然后由于视图模型对象以某种方式更改而重新分组,则该项目在移动到新组时将被取消选择。

重新分组所选项目时如何保留选择?

这是一个显示问题的简单精简 XAML 示例。如果 AllItems 中某个对象的 Category 属性发生更改,则该项目将通过实时整形正确重新分组。但是,如果该项目被选中,它将变为未选中状态。

<Grid>

    <Grid.Resources>
        <CollectionViewSource x:Key="MyItems" Source="{Binding AllItems}" IsLiveGroupingRequested="True" IsLiveSortingRequested="True">
            <CollectionViewSource.SortDescriptions>
                <componentModel:SortDescription PropertyName="Category" />
                <componentModel:SortDescription PropertyName="Name" />
            </CollectionViewSource.SortDescriptions>
            <CollectionViewSource.GroupDescriptions>
                <PropertyGroupDescription PropertyName="Category" />
            </CollectionViewSource.GroupDescriptions>
        </CollectionViewSource>
    </Grid.Resources>

    <ListBox ItemsSource="{Binding Source={StaticResource MyItems}}">
        <ListBox.GroupStyle>
            <GroupStyle>
                <GroupStyle.HeaderTemplate>
                        <DataTemplate>
                                <TextBlock Text="{Binding Name}" />
                        </DataTemplate>
                </GroupStyle.HeaderTemplate>
            </GroupStyle>
        </ListBox.GroupStyle>
    </ListBox>

</Grid>
4

2 回答 2

2

目前没有简单的解决方案。

我可以看到两种解决方案:

1) 用户手动停止实时更新。允许使用跳跃数据很容易出错。

示例:MS 中 WCF 日志查看器中的暂停按钮。

2) 在开始更新数据之前,请记住选择的项目。当更新完成时,只返回选择。

示例:如何防止 WPF DataGrid 在项目更新时取消选择 SelectedItem?

于 2013-08-28T11:41:11.973 回答
0

就我而言,我很少需要在视图模型中将所选项目设置为 null。所以我使用以下解决方法。请注意必须调用不同的方法来将选定值设置为 null 的尴尬方式。

private ItemViewModel selectedItem;
private ItemViewModel prevSelectedItem;

/// <summary>
/// Gets or sets the selected item. Use <see cref="ClearSelectedItem"/> to set it to null.
/// </summary>
public ItemViewModel SelectedItem
{
    get => selectedItem;
    set
    {
        if (!Equals(selectedItem, value))
        {
            prevSelectedItem = selectedItem;
            selectedItem = value;
            RaisePropertyChanged();
            if (value == null)
            {
                // Ignore null set by the live grouping/sorting/filtering in the CollectionViewSource
                System.Windows.Application.Current.MainWindow.Dispatcher.BeginInvoke(
                    new Action(() =>
                    {
                        SelectedItem = prevSelectedItem;
                    }));
            }
        }
    }
}

/// <summary>
/// Sets <see cref="SelectedItem"/> to null.
/// </summary>
public void ClearSelectedItem()
{
    selectedItem = null;
    RaisePropertyChanged(nameof(SelectedItem));
}

public event PropertyChangedEventHandler PropertyChanged;

/// <summary>
/// Raises a <see cref="PropertyChanged"/> event for the specified property name.
/// </summary>
/// <param name="propertyName">The name of the property to notify.</param>
protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
于 2022-02-01T20:48:10.927 回答