简体   繁体   中英

Change SelectedItem of ListBox from ViewModel

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM