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

前端 未结 1 487
你的背包
你的背包 2021-01-27 08:39

About my Project: I want to Highlight over a Search function ListboxItems trough their Index.

Current Stage:

private void Menu_Search_Click(object sender         


        
1条回答
  •  礼貌的吻别
    2021-01-27 08:57

    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 _execute;
        private readonly Func _canExecute;
    
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
    
        public RelayCommand(Action execute, Func 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 _persons;
        private ICommand _searchCommand;
    
        public ObservableCollection 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
            {
                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

    
        
            
        
        
            
                
                
            
            
                
                

    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

    
        
            
        
        
            
                
            
        
    
    

    0 讨论(0)
    提交回复
    热议问题