How can I get the SelectedItem
of a ListBox
to be highlighted after setting the SelectedItem
in the ViewModel?
The ItemsSource
is bound to an ObservableCollection
of Bar
(the collection is a member of a class Foo
. A button is bound to a command that adds a new empty Bar
instance to the collection and then also sets SelectedItem
to the new empty instance.
After adding the instance to the collection, the ListBox
is updated to show the new blank Bar
. However, after setting the SelectedItem
property in the ViewModel, the new instance is not highlighted in the ListBox
but it is being set and the PropertyChanged
event is raised (the SelectedItem
is displayed elsewhere in the View).
Additional Details:
INotifyPropertyChanged
is implemented in a base ViewModel class, and also implemented in the Foo
and Bar
classes.
The ListBox
contains a custom ItemTemplate
to display Bar
members, and a custom ItemContainerStyle
that modifies the Background
for the IsMouseOver
trigger.
simplified xaml:
<ListBox ItemsSource="{Binding Path=MyFoo.BarCollection}"
SelectedItem="{Binding Path=SelectedItem,
UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
<Button Content="Add New Bar"
Command="{Binding Path=AddBarCommand}"/>
simplified viewmodel:
private Foo _myFoo;
public Foo MyFoo
{
get { return _myFoo; }
set { _myFoo= value; OnPropertyChanged("MyFoo"); }
}
private Bar _selectedItem;
public Bar SelectedItem
{
get { return _selectedItem; }
set { _selectedItem = value; OnPropertyChanged("SelectedItem"); }
}
private void AddBar()
{
Bar newBar = new Bar();
MyFoo.BarCollection.Add(newBar);
SelectedItem = newBar ;
_unsavedChanges = true;
}
Your code worked perfectly for me.
Notice that "Bar 3" is selected, but when the listbox doesn't have focus, the default theme on Windows 7 works pretty hard to keep you from noticing. And Windows 7 isn't even the worst of the bunch. Our application uses WhiteSmoke
as a default background, and we've had major issues with older users 1 being unable to tell if listbox items are selected or not.
Fortunately, it's a trivial fix. These resources could just as easily be in Window.Resources
, in a global ListBox
style, or in App.xaml
. It's up to you how widely you want to apply them.
<ListBox
ItemsSource="{Binding MyFoo.BarCollection}"
SelectedItem="{Binding SelectedItem}"
>
<ListBox.Resources>
<SolidColorBrush
x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}"
Color="{x:Static SystemColors.HighlightColor}"
Opacity="0.5"
/>
<SolidColorBrush
x:Key="{x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}"
Color="{x:Static SystemColors.HighlightTextColor}"
/>
</ListBox.Resources>
</ListBox>
1 "Older" meaning old enough to vote.
And if your version of .NET predates the existence of SystemColors.InactiveSelectionHighlightTextBrushKey
, this could probably use some refinement, but it works:
<ListBox
>
<ListBox.ItemContainerStyle>
<Style
TargetType="ListBoxItem"
BasedOn="{StaticResource {x:Type ListBoxItem}}"
>
<Style.Setters>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid
Background="{TemplateBinding Background}"
>
<ContentPresenter />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter
Property="Background"
Value="{StaticResource {x:Static SystemColors.HighlightBrushKey}}"
/>
<Setter
Property="Foreground"
Value="{StaticResource {x:Static SystemColors.HighlightTextBrushKey}}"
/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True" />
<Condition Property="IsEnabled" Value="False" />
</MultiTrigger.Conditions>
<Setter
Property="Background"
Value="{StaticResource {x:Static SystemColors.InactiveCaptionBrushKey}}"
/>
</MultiTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.