Home > Mobile >  Select the associated ListViewItem when selecting a control inside the ListView DataTemplate
Select the associated ListViewItem when selecting a control inside the ListView DataTemplate

Time:09-08

I have a WinUI 3 ListView that displays a list of items. Every item has a ToggleSwitch and a Expander. When i click on the ToggleSwitch or the Expander the ListView selection does not change.

I found some solutions for WPF but they dont work in WinUI 3:

Selecting a Textbox Item in a Listbox does not change the selected item of the listbox

How can I do this for WinUI 3 so that the associated ListViewItem is selected when the ToggleSwitch or Expander is selected?

CodePudding user response:

You could handle the Tapped event for the Expander and ToggleSwitch and programmatically set the SelectedItem property of the ListView:

private void OnTapped(object sender, TappedRoutedEventArgs e)
{
    FrameworkElement element = (FrameworkElement)sender;
    lv.SelectedItem = element.DataContext;
}

XAML:

<ListView x:Name="lv">
    <ListView.ItemTemplate>
        <DataTemplate>
            ...
            <Expander Tapped="OnTapped" ... />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

CodePudding user response:

If you don't want to change selection when you do something programmatically, you can do it this way.

.xaml

<StackPanel>
    <Button
        Command="{x:Bind ViewModel.TestCommand}"
        Content="Click" />
    <ListView
        x:Name="ListViewControl"
        ItemsSource="{x:Bind ViewModel.Items}"
        SelectionMode="Single">
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="local:Item">
                <StackPanel>
                    <ToggleSwitch Toggled="ToggleSwitch_Toggled" />
                    <Expander Expanding="Expander_Expanding" IsExpanded="{x:Bind IsChecked, Mode=OneWay}" />
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</StackPanel>

.xaml.cs

private void ToggleSwitch_Toggled(object sender, RoutedEventArgs e)
{
    if (ViewModel.IsProgrammatical is false)
    {
        ListViewControl.SelectedItem = (sender as ToggleSwitch)?.DataContext;
    }
}

private void Expander_Expanding(Expander sender, ExpanderExpandingEventArgs args)
{
    if (ViewModel.IsProgrammatical is false)
    {
        ListViewControl.SelectedItem = sender.DataContext;
    }
}

ViewModel.cs

public partial class Item : ObservableObject
{
    [ObservableProperty]
    private string text = string.Empty;
    [ObservableProperty]
    private bool isChecked;
}

public partial class MainWindowViewModel : ObservableObject
{
    public bool IsProgrammatical { get; set; }

    [ObservableProperty]
    private List<Item> items = new()
    {
        { new Item() { Text = "A", IsChecked = false,} },
        { new Item() { Text = "B", IsChecked = false,} },
        { new Item() { Text = "C", IsChecked = false,} },
    };

    [RelayCommand]
    private void Test()
    {
        IsProgrammatical = true;
        Items[1].IsChecked = !Items[1].IsChecked;
        IsProgrammatical = false;
    }
}

Walkaround

In this case, the source collection is untouchable and we can't use a flag if the property was changed programmatically or not, we need to use the Tapped event to make the item selected. But unfortunately, the ToggleSwitch's Tapped event is not fired (at least in my environment). Might be a WinUI bug.

As a walkaround, at least until this bug gets fixed, you can use the ToggleButton. I tested out and the Tapped event is fired.

<DataTemplate x:DataType="local:Item">
    <StackPanel>
        <ToggleButton Tapped="ToggleButton_Tapped" />
        <Expander Tapped="Expander_Tapped" IsExpanded="{x:Bind IsChecked, Mode=OneWay}" />
    </StackPanel>
</DataTemplate>
private void ToggleButton_Tapped(object sender, TappedRoutedEventArgs e)
{
    ListViewControl.SelectedItem = (sender as ToggleSwitch)?.DataContext;
}

private void Expander_Tapped(Expander sender, TappedRoutedEventArgs e)
{
    ListViewControl.SelectedItem = sender.DataContext;
}
  • Related