You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinUI 3中ListView选中项无法在其他列表显示的绑定问题

WinUI 3 ListView多选选中项绑定失效的解决方案

问题根源

WinUI 3 中 ListView.SelectedItems 并非依赖属性,直接通过 XAML 绑定无法监听其变化,这是你两种尝试都失效的核心原因——和数据源使用 IEnumerable 无关,哪怕换成 ObservableCollection,直接绑定 SelectedItems 依然无效。

解决方案

以下提供两种方案,尽量满足你「仅通过XAML实现只读展示」的需求:

方案一:纯XAML+转换器(无需修改ViewModel)

通过转换器将 SelectedItems 转为可枚举集合,实现绑定展示:

  1. 创建转换器类
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Controls;
using System.Collections.Generic;
using System.Linq;

public class SelectedItemsConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        return value is IList<object> items ? items.ToList() : Enumerable.Empty<object>();
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}
  1. 在XAML中引用并使用
<Page.Resources>
    <local:SelectedItemsConverter x:Key="SelectedItemsConverter"/>
</Page.Resources>

<!-- 原ListView -->
<ListView
        x:Name="FlagsListView"
        SelectionMode="Multiple"
        ItemsSource="{x:Bind ViewModel.ValidationFlagsList, Mode=OneTime}"
        SelectedValuePath="Key"
        DisplayMemberPath="Value">
</ListView>

<!-- 展示选中项的ItemsControl -->
<ItemsControl ItemsSource="{Binding ElementName=FlagsListView, Path=SelectedItems, Converter={StaticResource SelectedItemsConverter}}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Value}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Vertical"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

方案二:附加属性+MVVM(更贴合Template Studio架构)

通过附加属性将 SelectedItems 包装为可绑定的依赖属性,适配MVVM模式:

  1. 创建附加属性类
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System.Collections.Generic;

public static class ListViewExtensions
{
    public static readonly DependencyProperty SelectedItemsProperty =
        DependencyProperty.RegisterAttached(
            "SelectedItems",
            typeof(IEnumerable<object>),
            typeof(ListViewExtensions),
            new PropertyMetadata(null, OnSelectedItemsChanged));

    public static IEnumerable<object> GetSelectedItems(DependencyObject obj)
    {
        return (IEnumerable<object>)obj.GetValue(SelectedItemsProperty);
    }

    public static void SetSelectedItems(DependencyObject obj, IEnumerable<object> value)
    {
        obj.SetValue(SelectedItemsProperty, value);
    }

    private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is ListView listView)
        {
            listView.SelectionChanged -= ListView_SelectionChanged;
            if (e.NewValue != null)
            {
                listView.SelectionChanged += ListView_SelectionChanged;
            }
        }
    }

    private static void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (sender is ListView listView)
        {
            var selectedItems = new List<object>();
            foreach (var item in listView.SelectedItems)
            {
                selectedItems.Add(item);
            }
            SetSelectedItems(listView, selectedItems);
        }
    }
}
  1. ViewModel中添加绑定属性
private IEnumerable<KeyValuePair<string, string>> _selectedFlags;
public IEnumerable<KeyValuePair<string, string>> SelectedFlags
{
    get => _selectedFlags;
    set => SetProperty(ref _selectedFlags, value);
}
  1. XAML中绑定使用
<ListView
        x:Name="FlagsListView"
        SelectionMode="Multiple"
        ItemsSource="{x:Bind ViewModel.ValidationFlagsList, Mode=OneTime}"
        SelectedValuePath="Key"
        DisplayMemberPath="Value"
        local:ListViewExtensions.SelectedItems="{x:Bind ViewModel.SelectedFlags, Mode=OneWayToSource}">
</ListView>

<!-- 展示选中项 -->
<ItemsControl ItemsSource="{x:Bind ViewModel.SelectedFlags, Mode=OneWay}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Value}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

关键说明

  • 数据源用 IEnumerable 完全没问题,你的场景是只读列表,OneTime 绑定足够;
  • 两种方案都能实现选中项的只读展示,转换器方案更偏向纯XAML,附加属性方案更适配MVVM架构。

内容的提问来源于stack exchange,提问作者Mihai Socaciu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 15:35:33