Problem: Losing ListView Item focus and as a consequence reset of SelectedItem property when I try to push button on another panel different from panel with ListView. I need to keep focus (optional) and keep SelectedItem value
If I click "Test1" value in red border is right. But after click "Test3" it reset.
Problem in styling of ListView. If remove trigger in ListControl.xaml (see full code below)
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsSelected" Value="True" />
</Trigger>
this problem will be resolved. But in this case pushing to "Test1" & "Test2" buttons not focused row and not set SelectedItem value.
MainWindow.xaml:
<Window x:Class="ListViewSample.MainWindow"
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:localVM="clr-namespace:ListViewSample"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<localVM:MainViewModel/>
</Window.DataContext>
<Grid>
<localVM:ListControl></localVM:ListControl>
</Grid>
</Window>
ListControl.xaml:
<UserControl x:Class="ListViewSample.ListControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ListViewSample"
d:DataContext="{d:DesignInstance Type=local:MainViewModel}"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="500">
<UserControl.Resources>
<SolidColorBrush x:Key="WindowBackground" Color="White" Opacity="0.75"/>
<Style x:Key="ListViewItemStyle" TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsSelected" Value="True" />
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListView Grid.Row="0" ItemsSource="{Binding ParametersList}" SelectedItem="{Binding SelectedItem}" ItemContainerStyle="{StaticResource ListViewItemStyle}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<Button Content="Test1" Margin="5" Height="30" Width="50" Command="{Binding PushButtonPnl}" />
<Button Content="Test2" Margin="5" Height="30" Width="50" Command="{Binding PushButtonPnl}" />
<TextBlock Text="{Binding Id}" />
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding Value}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Border x:Name="stkEasyLocatePanel" Grid.Row="0" Margin="5" Padding="5" BorderBrush="Black" BorderThickness="1,1,1,1" CornerRadius="5" Background="{DynamicResource WindowBackground}" Width="400" HorizontalAlignment="Right" >
<StackPanel>
<Border Margin="5" Padding="5" BorderBrush="Red" BorderThickness="1,1,1,1" CornerRadius="5">
<TextBlock Text="{Binding SelectedItem.Value}" FontSize="40" Foreground="Red" VerticalAlignment="Center"/>
</Border>
<StackPanel Orientation="Horizontal">
<Ellipse Margin="5" Height="30" Width="30" HorizontalAlignment="Left" VerticalAlignment="Center" Stroke="Black" Fill="Red"/>
<Ellipse Margin="5" Height="30" Width="30" HorizontalAlignment="Left" VerticalAlignment="Center" Stroke="Black" Fill="Orange"/>
<Ellipse Margin="5" Height="30" Width="30" HorizontalAlignment="Left" VerticalAlignment="Center" Stroke="Black" Fill="Yellow"/>
<Ellipse Margin="5" Height="30" Width="30" HorizontalAlignment="Left" VerticalAlignment="Center" Stroke="Black" Fill="Green"/>
<Ellipse Margin="5" Height="30" Width="30" HorizontalAlignment="Left" VerticalAlignment="Center" Stroke="Black" Fill="LightBlue"/>
<Ellipse Margin="5" Height="30" Width="30" HorizontalAlignment="Left" VerticalAlignment="Center" Stroke="Black" Fill="Blue"/>
<Ellipse Margin="5" Height="30" Width="30" HorizontalAlignment="Left" VerticalAlignment="Center" Stroke="Black" Fill="Violet"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="Test3" Margin="5" Height="30" Width="50" Command="{Binding PushButtonPnl}" />
</StackPanel>
</StackPanel>
</Border>
<StackPanel Grid.Row="1" Orientation="Horizontal">
<Button Content="Add" Margin="5" Height="30" Width="50" Command="{Binding PushButton}"/>
<ToggleButton Content=">>" Margin="5" Height="30" Width="50">
<ToggleButton.Triggers>
<EventTrigger RoutedEvent="ToggleButton.Unchecked">
<BeginStoryboard>
<Storyboard x:Name="HideStackPanel">
<DoubleAnimation Storyboard.TargetName="stkEasyLocatePanel" Storyboard.TargetProperty="Width" From="0" To="400" Duration="0:0:1.0">
<DoubleAnimation.EasingFunction>
<PowerEase EasingMode="EaseIn" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Content">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value=">>" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="ToggleButton.Checked">
<BeginStoryboard>
<Storyboard x:Name="ShowStackPanel">
<DoubleAnimation Storyboard.TargetName="stkEasyLocatePanel" Storyboard.TargetProperty="Width" From="400" To="0" Duration="0:0:1.0">
<DoubleAnimation.EasingFunction>
<PowerEase EasingMode="EaseIn" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Content">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="<<" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ToggleButton.Triggers>
</ToggleButton>
</StackPanel>
</Grid>
</UserControl>
MainViewModel.cs:
using System.Collections.ObjectModel;
using System.Windows;
using Prism.Commands;
using Prism.Mvvm;
namespace ListViewSample
{
public class ParameterItem
{
public int Id { get; set; }
public string Name { get; set; }
public double Value { get; set; }
public ParameterItem(int id, string name, double value)
{
Id = id;
Name = name;
Value = value;
}
}
public class MainViewModel : BindableBase
{
int idx = 0;
double vle = 123.45d;
public ObservableCollection<ParameterItem> ParametersList { get; set; }
private ParameterItem _selectedItem;
public ParameterItem SelectedItem
{
get => _selectedItem;
set
{
SetProperty(ref _selectedItem, value, nameof(SelectedItem));
}
}
public DelegateCommand PushButton { get; }
public DelegateCommand PushButtonPnl { get; set; }
public MainViewModel()
{
ParametersList = new();
PushButton = new DelegateCommand(() =>
{
Something();
});
Something();
PushButtonPnl = new DelegateCommand(() =>
{
var txt = _selectedItem == null ? "NULL" : _selectedItem.Value.ToString();
MessageBox.Show(txt);
});
}
private void Something()
{
ParametersList.Add(new ParameterItem(idx++, $"Par{idx}", vle * idx));
}
}
}
When the trigger becomes invalid it will restore the original value of the
ListBoxItem.IsSelectedproperty, which wasfalse.The default behavior is already correct. Focus moves away but the item remains selected. This visual state is known as "SelectedUnfocused" (see ListBoxItem States).
To keep the visual selected feedback effect you must override the
ControlTemplateto implement the "SelectedUnfocused" state animation (recommended) or implement the selected trigger new (as this will remove the default triggers and therefore also remove the "SelectedUnfocused" visual state).For example: