Select ListboxItem over Index(Highlight as i would click on it)

It can be done with Binding, DataTrigger and INotifyPropertyChanged interface implementation (the power of WPF widely used in MVVM programming pattern).

I'll use MVVM approach for the example of what you asking for.

Example features

  • User may type any text in TextBox and press Search button, all items containing search text will be highlighted with yellow background.
Step 0: Helpers

The following class needed to notifying UI about change in Property. I'll derive from in other classes and simply call OnPropertyChanged() in property setters.

NotifyPropertyChanged.cs

public class NotifyPropertyChanged : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

In MVVM developers aren't using Click Event because there's more powerful Command exists. Next class implements ICommand interface (grabbed from the documentation page linked above). It needed for easy commands implementation in the main code.

RelayCommand.cs

public class RelayCommand : ICommand
{
    private readonly Action<object> _execute;
    private readonly Func<object, bool> _canExecute;

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter) => _canExecute == null || _canExecute(parameter);
    public void Execute(object parameter) => _execute(parameter);
}
Step 1: Data

Person.cs

public class Person : NotifyPropertyChanged
{
    private bool _highlighted;

    public string Name { get; set; }
    public bool Highlighted
    {
        get => _highlighted;
        set
        {
            _highlighted = value;
            OnPropertyChanged();
        }
    }
}
Step 2: View Model

View Model in MVVM is class where View (UI/XAML) may set its DataContext which required for Binding.

MainViewModel.cs

public class MainViewModel : NotifyPropertyChanged
{
    private ObservableCollection<Person> _persons;
    private ICommand _searchCommand;

    public ObservableCollection<Person> Persons
    {
        get => _persons;
        set
        {
            _persons = value;
            OnPropertyChanged();
        }
    }

    // It's C# 8.0 but for earlier versions of C# use the following:
    //                               _searchCommand ?? (_searchCommand = new ...
    public ICommand SearchCommand => _searchCommand ??= new RelayCommand(parameter =>
    {
        if (parameter is string searchText)
        {
            foreach(Person person in Persons)
            {
                person.Highlighted = searchText.Length > 0 && person.Name.Contains(searchText, StringComparison.InvariantCultureIgnoreCase);    
            }
        }
    });
    // }));

    public MainViewModel()
    {
        // example data
        Persons = new ObservableCollection<Person>
        {
            new Person { Name = "Alex" },
            new Person { Name = "Jane" },
            new Person { Name = "Nick" },
            new Person { Name = "John" },
            new Person { Name = "Brett" },
            new Person { Name = "Peter" },
            new Person { Name = "Mike" },
            new Person { Name = "George" },
            new Person { Name = "Anthony" }
        };
    }
}
Step 3: View

I'm providing the full markup to make everything clear. Here's DataContext setup and all the Controls.

MainWindow.xaml

<Window x:Class="WpfApp1.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:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal">
            <TextBox x:Name="SearchTextBox" Width="300" Margin="5"/>
            <Button Content="Search" Margin="5" Command="{Binding SearchCommand}" CommandParameter="{Binding Text,ElementName=SearchTextBox}"/>
        </StackPanel>
        <ListBox Margin="5" Grid.Row="1" ItemsSource="{Binding Persons}">
            <ListBox.Resources>
                <Style TargetType="ListBoxItem">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding Highlighted}" Value="True">
                            <Setter Property="Background" Value="Yellow"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </ListBox.Resources>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>

That's it.

P.S. Code-behind class :)

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
}

Updated

In case i was wrong with understanding the question and you need an automatic selection instead of highlight, the code may be changed in the following way:

Person.cs

public class Person : NotifyPropertyChanged
{
    private bool _selected;

    public string Name { get; set; }
    public bool Selected
    {
        get => _selected;
        set
        {
            _selected = value;
            OnPropertyChanged();
        }
    }
}

MainViewModel.cs

public ICommand SearchCommand => _searchCommand ??= new RelayCommand(parameter =>
{
    if (parameter is string searchText)
    {
        foreach(Person person in Persons)
        {
            person.Selected = searchText.Length > 0 && person.Name.Contains(searchText, StringComparison.InvariantCultureIgnoreCase);    
        }
    }
});

MainWindow.xaml

<ListBox Margin="5" Grid.Row="1" ItemsSource="{Binding Persons}" SelectionMode="Extended">
    <ListBox.Resources>
        <Style TargetType="ListBoxItem">
            <Setter Property="IsSelected" Value="{Binding Selected}"/>
        </Style>
    </ListBox.Resources>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>


Comments

  1. Mathias

    • 2018/2/3

    It can be done with Binding , DataTrigger and INotifyPropertyChanged interface implementation (the power of WPF widely used in MVVM 

  2. Fletcher

    • 2016/11/30

    The listbox has some items and when I click any of items the app navigates to a new page. From beginning to here, everything is good. But I want end-user can select the item again which causes navigate to the next page again. But listbox as it is, doesn't allow me to select an already selected item again.

  3. Tadeo

    • 2016/9/30

    Gets or sets the currently selected item in the ListBox. In addition, you can use the SelectedIndices property to obtain all the selected indexes in a 

  4. Franklin

    • 2015/12/3

    I have databinding in listbox, and my listboxitem template contains button (so each item in listbox contains its own button). And problem is that, when I click on the button in item, the Item will not get selected. And I need item to get selected on click on this button of item. Is there some way how to do this?

  5. Cullen

    • 2017/10/14

    In a UserForm, when you set the MultiSelect property to 1 - fmMultiSelectMulti for a ListBox control, you can select any number of items from a list.

  6. Bruce

    • 2018/9/3

    ListBoxItem’s default template can be easily inspected and modified using Expression Blend – Select a ListBoxItem in Objects and Timeline pane, Right click and select Edit template > Edit a Copy. Name you template and save it at the scope of your choice. This will create a copy of the template and allow you to modify it.

  7. Francis

    • 2020/8/23

    using listbox.SelectedItem = object to hightlight in the list. or listbox.SelectedIndex = numeric index of the item you want highlighted.

  8. Jeffery

    • 2015/11/4

    Sharing small stuffs I figure out while working with WPF !! Originally when you select any item in a ListBox control in WPF, you will observe that the background color of item turns LightBlue (if not using some kind of theming mechanism). Also when the ListBox control is not in focus

  9. Taylor

    • 2018/8/24

    I can't use select by index because the position of the item that it to the top of list box so we can reliably click on it to select it.

  10. Jayden

    • 2019/8/16

    The first procedure will select the first item in a list box by clicking on the command button (a macro button). Option Explicit Private Sub CommandButton1_Click () Dim i As Long For i = ListBox1.ListCount - 1 To 0 Step -1 ListBox1.ListIndex = i Next i End Sub The following procedure will select the last item in a list box.

  11. Crew

    • 2018/6/11

    You can open the Properties window by pressing F4 or by right-clicking on a control and selecting the "Properties" menu item. The Properties 

  12. Brixton

    • 2017/10/31

    On the Item Designer, select TListBoxGroupHeader from the drop-down list, and then select Add Item: Select TListBoxGroupFooter from the drop-down list, and then select Add Item. Select ListBoxGroupHeader1 in the list of items, and click the Up button several times until this item becomes the top item on the list: Close the dialog box.

  13. Angel

    • 2015/3/12

    Above code will return the itme from first column of first row. The user can (without selecting the item) just click the quantity dropdown and select a 

  14. Ira

    • 2017/5/19

    Multiple: The user can select multiple items from the list by just clicking them, without having to press any special keys to allow the multiple selection. private void button_Click(object sender, RoutedEventArgs e) { foreach (ListBoxItem item in lstbxCats.Items) { //Check to see whether it’s selected.

  15. Marcus

    • 2015/1/8

    You use a list box item's index to access the item. The index of the When an item is selected in a list box, the item appears highlighted in the list.

  16. Mazza

    • 2021/2/18

    ( Continued ) $ w yview index Shifts the display so the line at index is at the This is the default . multiple More than one element can be selected by 

  17. Raymond

    • 2016/10/2

    But now I want to make the email address hyperlink and link the email address via Select ListboxItem over Index(Highlight as i would click on it).

Comments are closed.

Recent Posts