问题:当我尝试按下与 ListView 面板不同的另一个面板上的按钮时,失去 ListView 项目焦点并因此重置 SelectedItem 属性。我需要保持焦点(可选)并保持 SelectedItem 值 如果我单击红色边框中的“Test1”值是正确的。但点击“Test3”后它会重置。 ListView 的样式问题。如果在 ListControl.xaml 中删除触发器(请参阅下面的完整代码)
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsSelected" Value="True" />
</Trigger>
这个问题将会得到解决。但在这种情况下,按下“Test1”和“Test2”按钮不会聚焦行,也不会设置 SelectedItem 值。
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));
}
}
}
当触发器无效时,它将恢复
ListBoxItem.IsSelected
属性的原始值,即 false
。
默认行为已经是正确的。焦点移开,但该项目仍保持选中状态。这种视觉状态称为“SelectedUnfocused”(请参阅ListBoxItem States)。
要保持视觉选定的反馈效果,您必须覆盖
ControlTemplate
以实现“SelectedUnfocused”状态动画(推荐)或实现新的选定触发器(因为这将删除默认触发器,因此也会删除“SelectedUnfocused”视觉状态).
例如:
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="{x:Static SystemColors.HighlightColor}"
Opacity="0.1" />
</Setter.Value>
</Setter>
<Setter Property="BorderBrush">
<Setter.Value>
<SolidColorBrush Color="{x:Static SystemColors.HighlightColor}"
Opacity="0.4" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsSelected"
Value="True">
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="{x:Static SystemColors.HighlightColor}"
Opacity="0.2" />
</Setter.Value>
</Setter>
<Setter Property="BorderBrush">
<Setter.Value>
<SolidColorBrush Color="{x:Static SystemColors.HighlightColor}"
Opacity="0.6" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsEnabled"
Value="False">
<Setter Property="Foreground"
Value="{x:Static SystemColors.GrayTextBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>