I'm making a simple ListView
with WinUI
and Microsoft.Toolkit.Mvvm
based on TemplateStudio for WinUI.
I try to achieve a simple ListView
that contains fruits names, a 2nd ListView
to get SelectedItems
from the first one and finally a TextBox
with count of selected items.
MainPage.xaml
<Page
x:Class="ListViewWinUISample.Views.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
mc:Ignorable="d">
<Grid x:Name="ContentArea" Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition Height="150" />
<RowDefinition Height="25" />
<RowDefinition Height="150" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="Fruits list :" Style="{StaticResource PageTitleStyle}" />
<ListView Grid.Row="1" x:Name="LvwFruits" ItemsSource="{x:Bind ViewModel.ListFruits}" BorderBrush="#212121" SelectionMode="Multiple">
<i:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="SelectionChanged">
<core:InvokeCommandAction Command="{x:Bind ViewModel.GetSelectedFruits}" CommandParameter="{Binding SelectedItems, ElementName=LvwFruits}"/>
</core:EventTriggerBehavior>
</i:Interaction.Behaviors>
</ListView>
<TextBlock Grid.Row="2" Text="Selected fruits :" Style="{StaticResource PageTitleStyle}" />
<ListView Grid.Row="3" x:Name="LvwSelectedFruits" ItemsSource="{x:Bind ViewModel.ListSelectedFruits}" BorderBrush="#212121"/>
<StackPanel Grid.Row="4" Orientation="Horizontal">
<TextBlock Text="Count selected fruits : " VerticalAlignment="Center"/>
<TextBox Text="{Binding SelectedItems.Count, ElementName=LvwFruits}" VerticalAlignment="Center"/>
</StackPanel>
</Grid>
</Page>
MainViewModel.cs
using System.Collections;
using System.Collections.ObjectModel;
using System.Diagnostics;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
namespace ListViewWinUISample.ViewModels;
public class MainViewModel : ObservableRecipient
{
public List<string> ListFruits;
public List<string> ListSelectedFruits;
public RelayCommand<IList> GetSelectedFruits { get; set; }
public MainViewModel()
{
GetSelectedFruits = new RelayCommand<IList>(GetSelectedFruitsMethod);
var fruits = new List<string>
{
"Apple",
"Banana",
"Strawberry"
};
ListFruits = fruits;
}
private void GetSelectedFruitsMethod(IList selectedFruits)
{
Debug.WriteLine("Command successfully executed");
var listSelectedFruits = new List<string>();
foreach (var item in selectedFruits)
{
listSelectedFruits.Add(item.ToString());
Debug.WriteLine("selected fruit : " + item.ToString());
}
}
}
The GetSelectedFruitsMethod
is successfully started but the parameter IList selectedFruits
in GetSelectedFruitsMethod
is always null
and I can't figure out how to get the SelectedItems
parameter from the View even if I passed it as CommandParameter
in XAML.
Thanks and regards.
I finally got the answer by myself with the full MVVM way.
To retrieve SelectedItems
from first ListView
, there was just to set CommandParameter="{x:Bind LvwFruits.SelectedItems}"
and not {Binding SelectedItems, ElementName=LvwFruits}
and to replace IList
by IList<object>
.
MainPage.xaml
<Page
x:Class="ListViewWinUISample.Views.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
mc:Ignorable="d">
<Grid x:Name="ContentArea" Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition Height="150" />
<RowDefinition Height="25" />
<RowDefinition Height="150" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="Fruits list :" Style="{StaticResource PageTitleStyle}" />
<ListView Grid.Row="1" x:Name="LvwFruits" ItemsSource="{x:Bind ViewModel.ListFruits}" BorderBrush="#212121" SelectionMode="Multiple" BorderThickness="1">
<i:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="SelectionChanged">
<core:InvokeCommandAction Command="{x:Bind ViewModel.GetSelectedFruits, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" CommandParameter="{x:Bind LvwFruits.SelectedItems}"/>
</core:EventTriggerBehavior>
</i:Interaction.Behaviors>
</ListView>
<TextBlock Grid.Row="2" Text="Selected fruits :" Style="{StaticResource PageTitleStyle}" />
<ListView Grid.Row="3" x:Name="LvwSelectedFruits" ItemsSource="{x:Bind ViewModel.ListSelectedFruits, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" CanDragItems="True" CanReorderItems="True" AllowDrop="True" SelectionMode="Single" BorderBrush="#212121" BorderThickness="1"/>
<StackPanel Grid.Row="4" Orientation="Horizontal">
<TextBlock Text="Count selected fruits : " VerticalAlignment="Center"/>
<TextBox Text="{x:Bind ViewModel.CountSelectedCommands, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Margin="5,0,0,0" Width="10"/>
</StackPanel>
</Grid>
</Page>
MainViewModel.cs
using System.Collections;
using System.Collections.ObjectModel;
using System.Diagnostics;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
namespace ListViewWinUISample.ViewModels;
public class MainViewModel : ObservableRecipient
{
public List<string> ListFruits;
private ObservableCollection<string> listSelectedFruits;
public ObservableCollection<string> ListSelectedFruits
{
get => listSelectedFruits;
set => SetProperty(ref listSelectedFruits, value);
}
private int countSelectedCommands;
public int CountSelectedCommands
{
get => countSelectedCommands;
set => SetProperty(ref countSelectedCommands, value);
}
public RelayCommand<IList<object>> GetSelectedFruits
{
get; set;
}
public MainViewModel()
{
GetSelectedFruits = new RelayCommand<IList<object>>(GetSelectedFruitsMethod);
var fruits = new List<string>
{
"Apple",
"Banana",
"Strawberry"
};
ListFruits = fruits;
}
private void GetSelectedFruitsMethod(IList<object> selectedFruits)
{
if (selectedFruits != null)
{
var selected = new ObservableCollection<string>();
foreach (var item in selectedFruits)
{
selected.Add(item.ToString());
Debug.WriteLine("Selected fruit : " + item.ToString());
}
ListSelectedFruits = selected;
CountSelectedCommands = selected.Count;
}
else
{
Debug.WriteLine(@"/!\ NO SELECTED FRUITS /!\");
}
}
}