【问题标题】:WinUI 3 ListView - how to select item programmatically in mvvm?WinUI 3 ListView - 如何在 mvvm 中以编程方式选择项目?
【发布时间】:2022-11-16 22:20:25
【问题描述】:

如果用户与我们在代码后面添加/删除的列表视图交互,我们有一个可观察的集合SelectedPartys

<ListView
    x:Name="LV_Partys"
    IsMultiSelectCheckBoxEnabled="True"
    ItemsSource="{x:Bind ViewModel.PartysOC, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
    SelectionChanged="LV_Partys_SelectionChanged"
    SelectionMode="Extended">

    <ListView.ItemTemplate>
        <DataTemplate>

            <Grid Margin="0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>

                <StackPanel Grid.Row="0" Orientation="Horizontal">
                    <TextBlock Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" TextWrapping="NoWrap" />
                </StackPanel>

            </Grid>

        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>
private ObservableCollection<Party> partysOC;
public ObservableCollection<Party> PartysOC
{
    get => partysOC;
    set => Set(ref partysOC, value);
}

private void LV_Partys_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    var added_items = e.AddedItems.Cast<Party>().ToList();
    foreach (var item in added_items)
    {
        ViewModel.SelectedPartys.Add(item);
    }

    var removed_items = e.RemovedItems.Cast<Party>().ToList();
    foreach (var item in removed_items)
    {
        ViewModel.SelectedPartys.Remove(item);
    }

    ViewModel.SelectedPartyChanged();
}

我们需要将ListViews选中的item保存到Db中,然后恢复预选在 ListView 中,为此我相信我们需要以编程方式选择一个项目,我们该怎么做?

【问题讨论】:

    标签: c# listview mvvm winui-3


    【解决方案1】:

    由于您不能绑定到SelectedItems,您可能需要创建一个派生自ListView的控件:

    自定义列表视图.cs

    using Microsoft.UI.Xaml;
    using Microsoft.UI.Xaml.Controls;
    using Microsoft.UI.Xaml.Data;
    using Windows.Foundation.Collections;
    
    namespace ListViews;
    
    public class CustomListView : ListView
    {
        public static readonly DependencyProperty SelectedItemsSourceProperty = DependencyProperty.Register(
            nameof(SelectedItemsSource),
            typeof(object),
            typeof(CustomListView),
            new PropertyMetadata(default, (d, e) =>
            {
                (d as CustomListView)?.UpdateSelectedItemsSource();
            }));
    
        public object SelectedItemsSource
        {
            get => (object)GetValue(SelectedItemsSourceProperty);
            set => SetValue(SelectedItemsSourceProperty, value);
        }
    
        private CollectionViewSource? SelectedItemsSourceViewSource { get; set; }
    
        private ICollectionView? SelectedItemsSourceView { get; set; }
    
        private void UpdateSelectedItemsSource()
        {
            if (SelectedItemsSourceView is not null)
            {
                SelectedItemsSourceView.VectorChanged -= SelectedItemsSourceView_VectorChanged;
            }
    
            SelectedItemsSourceViewSource = new()
            {
                Source = SelectedItemsSource
            };
    
            SelectedItemsSourceView = SelectedItemsSourceViewSource.View;
            SelectedItemsSourceView.VectorChanged += SelectedItemsSourceView_VectorChanged;
        }
    
        private void SelectedItemsSourceView_VectorChanged(IObservableVector<object> sender, IVectorChangedEventArgs @event)
        {
            switch (@event.CollectionChange)
            {
                case CollectionChange.Reset:
                    SelectedItems.Clear();
                    break;
    
                case CollectionChange.ItemInserted:
                    if (SelectedItemsSourceView?.Count >= @event.Index)
                    {
                        SelectedItems.Add(SelectedItemsSourceView[(int)@event.Index]);
                    }
                    break;
    
                case CollectionChange.ItemRemoved:
                    if (SelectedItemsSourceView?.Count >= @event.Index)
                    {
                        SelectedItems.Remove(SelectedItemsSourceView[(int)@event.Index]);
                    }
                    break;
    
                case CollectionChange.ItemChanged:
                    break;
    
                default:
                    break;
            }
        }
    }
    

    并像这样使用它:

    主页.xaml

    <local:CustomListView
        ItemsSource="{x:Bind ViewModel.Items, Mode=OneWay}"
        SelectedItemsSource="{x:Bind ViewModel.SelectedItems, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
        SelectionMode="Multiple">
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="local:Item">
                <TextBlock Text="{x:Bind Id}" />
            </DataTemplate>
        </ListView.ItemTemplate>
    </local:CustomListView>
    

    【讨论】:

    • 谢谢,我会看看这个。现在我已经创建了一个我发布的解决方案来完成这项工作但需要使用 MVVM 消息总线。
    • ListView 确实有一个 SelectedItems 属性,遗憾的是 MS 将其设为只读而不是 DP。
    • 作品请客,欣赏。无法相信这不是标准功能。
    【解决方案2】:

    WinUI 3 ListView 上有一个方法叫YourListView.SelectRange()

    它在 xaml 中的 ListView 上不可用,因此我在 MVVM 消息传递调用后面的代码中调用它。

    视图代码隐藏文件

    public CodeBehindConstructor()
    {
        this.InitializeComponent();
    
        // Rx ListView Select items
        WeakReferenceMessenger.Default.Register<Msg_ListView_SelectItems>(this, (r, msg) =>
        {
            SelectParty(msg.Start, msg.Length);
        });
    }
    
    
    public void SelectParty(int start, uint length)
    {
        Debug.WriteLine($"SelectParty  start {start}   len {length}");
        LV_Partys.SelectRange(new ItemIndexRange(start, length));
    }
    

    视图模型

        // Select 1st Party 
        WeakReferenceMessenger.Default.Send(new Msg_ListView_SelectItems { Start = 0, Length = 1});// Start is 0 based, Length isnt it starts at 1
    
        // Select 2nd Party 
        WeakReferenceMessenger.Default.Send(new Msg_ListView_SelectItems { Start = 1, Length = 1 });
    

    Msg_ListView_SelectItems 类

    public class Msg_ListView_SelectItems
    {
        public int Start { get; set; }
        public uint Length { get; set; }
    }
    

    如果您的 ListViews 选择模式是 MultipleExtended 然后 .SelectRange() 选择连续批次的商品,因此您可以多次致电SelectRange 购买非连续订单的商品。

    【讨论】:

      猜你喜欢
      • 2019-12-17
      • 2013-12-25
      • 1970-01-01
      • 2011-08-13
      • 2023-01-25
      • 2010-10-08
      • 2010-11-07
      • 2022-10-04
      • 1970-01-01
      相关资源
      最近更新 更多