加载 WPF 时在 ListBox 中设置 SelectedItem 的样式
Style SelectedItem in ListBox upon Load WPF
我有一个ListBox
,因此:
<ListBox
//other stuff
ItemsSource="{Binding ViewModels, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding SelectedThing, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Purple" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
ViewModel.cs:
public SomeType SelectedThing
{
get => selectedThing;
set => //set with INotifyPropertyChanged
}
public ObservableCollection<SomeType> ViewModels
{
get => viewModels;
set => //set with INotifyPropertyChanged
}
可能 SelectedThing
在加载应用程序时在 ViewModel
中定义,因此我希望它具有相应的样式。
当我打开应用程序然后点击一个项目时效果很好,但是如何在加载时应用样式?
我试过:
<Style.Triggers>
<DataTrigger Binding="{Binding IsEnabled, RelativeSource={RelativeSource Mode=Self}}" Value="True">
<Setter Property="Background" Value="Purple" />
</DataTrigger>
</Style.Triggers>
但是 ListBox
的每个项目都已启用,因此它会在加载时将其应用于每个项目。
编辑:
稍加调试后,我发现在加载时设置SelectedThing
时,SelectedItem
仍然是null
。
编辑:
这是 ViewModel
中的 OnLoaded
方法,如果用户在之前使用该应用程序时选择了它,我将在其中设置 SelectedThing
。目的是在关闭并重新打开应用程序后保留选择。
public IAsyncRelayCommand OnLoadedCommand { get; set; }
在构造函数中:
OnLoadedCommand = new AsyncRelayCommand(OnLoaded);
在视图中:
<b:Interaction.Triggers>
<b:EventTrigger EventName="Loaded">
<b:InvokeCommandAction Command="{Binding OnLoadedCommand}" />
</b:EventTrigger>
</b:Interaction.Triggers>
实际方法:
public async Task OnLoaded()
{
//other stuff
if (App.Current.Properties.Contains(nameof(SelectedThing)))
{
var selected = JsonConvert.DeserializeObject<SomeType>(App.Current.Properties[nameof(SelectedThing)].ToString());
SelectedThing = selected;
}
}
未选择项目的原因是您将 SelectedThing
来源 属性 设置为不在 ViewModels
来源集合中的值。
正如您已经发现的那样,这种方法效果更好:
var selectedViewModel = ViewModels.Where(x => x.SelectedThing == selected.SelectedThing).FirstOrDefault();
SelectedThing = selectedViewModel;
要选择的项目必须存在于源集合中。
我有一个ListBox
,因此:
<ListBox
//other stuff
ItemsSource="{Binding ViewModels, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding SelectedThing, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Purple" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
ViewModel.cs:
public SomeType SelectedThing
{
get => selectedThing;
set => //set with INotifyPropertyChanged
}
public ObservableCollection<SomeType> ViewModels
{
get => viewModels;
set => //set with INotifyPropertyChanged
}
可能 SelectedThing
在加载应用程序时在 ViewModel
中定义,因此我希望它具有相应的样式。
当我打开应用程序然后点击一个项目时效果很好,但是如何在加载时应用样式?
我试过:
<Style.Triggers>
<DataTrigger Binding="{Binding IsEnabled, RelativeSource={RelativeSource Mode=Self}}" Value="True">
<Setter Property="Background" Value="Purple" />
</DataTrigger>
</Style.Triggers>
但是 ListBox
的每个项目都已启用,因此它会在加载时将其应用于每个项目。
编辑:
稍加调试后,我发现在加载时设置SelectedThing
时,SelectedItem
仍然是null
。
编辑:
这是 ViewModel
中的 OnLoaded
方法,如果用户在之前使用该应用程序时选择了它,我将在其中设置 SelectedThing
。目的是在关闭并重新打开应用程序后保留选择。
public IAsyncRelayCommand OnLoadedCommand { get; set; }
在构造函数中:
OnLoadedCommand = new AsyncRelayCommand(OnLoaded);
在视图中:
<b:Interaction.Triggers>
<b:EventTrigger EventName="Loaded">
<b:InvokeCommandAction Command="{Binding OnLoadedCommand}" />
</b:EventTrigger>
</b:Interaction.Triggers>
实际方法:
public async Task OnLoaded()
{
//other stuff
if (App.Current.Properties.Contains(nameof(SelectedThing)))
{
var selected = JsonConvert.DeserializeObject<SomeType>(App.Current.Properties[nameof(SelectedThing)].ToString());
SelectedThing = selected;
}
}
未选择项目的原因是您将 SelectedThing
来源 属性 设置为不在 ViewModels
来源集合中的值。
正如您已经发现的那样,这种方法效果更好:
var selectedViewModel = ViewModels.Where(x => x.SelectedThing == selected.SelectedThing).FirstOrDefault();
SelectedThing = selectedViewModel;
要选择的项目必须存在于源集合中。