I have a WinUI 3 project scaffolded using Template Studio. I have a list view populated with an Enum. I want to show my selected items in another list, but the binding does not work.
Populated with Enum meaning I take <key, value> pairs with enum value and enum description and use as ItemsSource. Selection Mode Multiple active.
public IEnumerable<KeyValuePair<string, string>> ValidationFlagsList => EnumExtensions.GetAllValuesAndDescriptions<ValidationFlag>();
//...
public static IEnumerable<KeyValuePair<string, string>> GetAllValuesAndDescriptions<TEnum>() where TEnum : struct, IConvertible, IComparable, IFormattable
{
return typeof(TEnum).IsEnum ? (from e in Enum.GetValues(typeof(TEnum)).Cast<Enum>() select new KeyValuePair<string, string>(e.ToString(), e.GetDescription())) : throw new ArgumentException("TEnum must be an Enumeration type");
}
<ListView
x:Name="FlagsListView"
SelectionMode="Multiple"
ItemsSource="{x:Bind ViewModel.ValidationFlagsList, Mode=OneTime}"
SelectedValuePath="Key"
DisplayMemberPath="Value">
</ListView>
In another part of xaml I want to show the selected items. I tried two variants:
1.
<ListView ItemsSource="{Binding SelectedItems, ElementName=FlagsListView, Mode=OneWay}"/>
2.
<StackPanel DataContext="{Binding SelectedItems, ElementName=FlagsListView}">
<TextBlock Text="{Binding}"/>
</StackPanel>
Nothing shows on UI. How can I bind correctly?
Is it because IEnumerable is static and ObservableCollection is needed? But the xaml ListView should give me some straightforward binding. Documentation points to this Data binding. I read about creating a class with IsSelected property, but I only need a readonly list, preferably to add something only in xaml.
The ListView does have a SelectedItems property but it's just a plain property and not a DependencyProperty
. Unfortunately you can't use it with bindings.
What you can do is create a custom ListView
:
ListViewEx.cs
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System.Collections;
using System.Collections.Generic;
namespace ListViews;
public class ListViewEx : ListView
{
public ListViewEx() : base()
{
this.SelectionChanged += ListViewEx_SelectionChanged;
}
public new IList SelectedItems
{
get => (IList)GetValue(SelectedItemsProperty);
set => SetValue(SelectedItemsProperty, value);
}
public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register(
nameof(SelectedItems),
typeof(IList),
typeof(ListViewEx),
new PropertyMetadata(new ObservableCollection<object>()));
private void ListViewEx_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
foreach (object item in e.RemovedItems)
{
SelectedItems.Remove(item);
}
foreach (object item in e.AddedItems)
{
SelectedItems.Add(item);
}
}
}
and use it like this:
<Grid ColumnDefinitions="*,*">
<local:ListViewEx
x:Name="FlagsListView"
Grid.Column="0"
DisplayMemberPath="Value"
ItemsSource="{x:Bind ViewModel.ValidationFlagsList, Mode=OneTime}"
SelectedValuePath="Key"
SelectionMode="Multiple" />
<ListView
Grid.Column="1"
ItemsSource="{x:Bind FlagsListView.SelectedItems, Mode=OneWay}" />
</Grid>