📜  带有搜索栏的列表uwp c#(1)

📅  最后修改于: 2023-12-03 15:09:44.001000             🧑  作者: Mango

带有搜索栏的列表 UWP C#

在 UWP 应用程序中,我们经常需要向用户展示数据列表,并且为了方便用户查找特定项,我们通常会添加搜索栏。在本文中,我们将介绍如何实现一个带有搜索栏的列表。

控件选择

我们将使用 ListView 控件来展示数据列表,使用 TextBox 控件作为搜索栏。

实现步骤
  1. 创建一个类用来保存列表中的项的数据。这个类需要实现 INotifyPropertyChanged 接口,以便我们能够及时通知界面更新。例如:
public class ListItem : INotifyPropertyChanged
{
    private string _title;
    public string Title
    {
        get { return _title; }
        set
        {
            _title = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    
    protected void OnPropertyChanged([CallerMemberName] string name = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}
  1. 在 XAML 文件中添加 ListViewTextBox 控件,并绑定它们的属性。例如:
<StackPanel>
    <TextBox x:Name="txtSearch" PlaceholderText="Search" 
             Text="{Binding SearchText, Mode=TwoWay}" 
             Margin="10"/>
    <ListView x:Name="listView" ItemsSource="{Binding FilteredList}" 
              Margin="10">
        <ListView.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Title}"/>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</StackPanel>

注意,TextBoxText 属性需要绑定到一个名为 SearchText 的属性,这个属性用来保存用户输入的搜索关键字。ListViewItemsSource 属性需要绑定到一个名为 FilteredList 的属性,这个属性用来保存经过过滤后的列表项。

  1. 创建 ViewModel 类来处理业务逻辑。ViewModel 类需要实现 INotifyPropertyChanged 接口,并声明 SearchTextFilteredList 两个属性。例如:
public class ListViewModel : INotifyPropertyChanged
{
    private string _searchText;
    public string SearchText
    {
        get { return _searchText; }
        set
        {
            _searchText = value;
            FilterList();
            OnPropertyChanged();
        }
    }

    private ObservableCollection<ListItem> _listItems;
    public ObservableCollection<ListItem> ListItems
    {
        get { return _listItems; }
        set
        {
            _listItems = value;
            FilterList();
            OnPropertyChanged();
        }
    }

    private ObservableCollection<ListItem> _filteredList;
    public ObservableCollection<ListItem> FilteredList
    {
        get { return _filteredList; }
        set
        {
            _filteredList = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    
    public ListViewModel()
    {
        // 初始化列表数据
        ListItems = new ObservableCollection<ListItem>
        {
            new ListItem { Title = "Item 1" },
            new ListItem { Title = "Item 2" },
            new ListItem { Title = "Item 3" },
            //...
        };
    }

    private void FilterList()
    {
        if (ListItems != null && !string.IsNullOrEmpty(SearchText))
        {
            var filtered = ListItems.Where(i => i.Title.ToLower().Contains(SearchText.ToLower()))
                                    .ToList();
            FilteredList = new ObservableCollection<ListItem>(filtered);
        }
        else
        {
            FilteredList = ListItems;
        }
    }
    
    protected void OnPropertyChanged([CallerMemberName] string name = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

在 ViewModel 类的构造函数中,我们初始化列表数据。在 FilterList() 方法中,我们根据用户输入的搜索关键字过滤列表项,并保存到 FilteredList 属性中。

  1. 在页面的 OnNavigatedTo 方法中,我们创建 ViewModel 对象,并将视图和 ViewModel 绑定。例如:
private ListViewModel _viewModel;

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    _viewModel = new ListViewModel();
    DataContext = _viewModel;
}

这样,我们就完成了带有搜索栏的列表的实现。

完整代码

ViewModel:

public class ListViewModel : INotifyPropertyChanged
{
    private string _searchText;
    public string SearchText
    {
        get { return _searchText; }
        set
        {
            _searchText = value;
            FilterList();
            OnPropertyChanged();
        }
    }

    private ObservableCollection<ListItem> _listItems;
    public ObservableCollection<ListItem> ListItems
    {
        get { return _listItems; }
        set
        {
            _listItems = value;
            FilterList();
            OnPropertyChanged();
        }
    }

    private ObservableCollection<ListItem> _filteredList;
    public ObservableCollection<ListItem> FilteredList
    {
        get { return _filteredList; }
        set
        {
            _filteredList = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    
    public ListViewModel()
    {
        // 初始化列表数据
        ListItems = new ObservableCollection<ListItem>
        {
            new ListItem { Title = "Item 1" },
            new ListItem { Title = "Item 2" },
            new ListItem { Title = "Item 3" },
            //...
        };
    }

    private void FilterList()
    {
        if (ListItems != null && !string.IsNullOrEmpty(SearchText))
        {
            var filtered = ListItems.Where(i => i.Title.ToLower().Contains(SearchText.ToLower()))
                                    .ToList();
            FilteredList = new ObservableCollection<ListItem>(filtered);
        }
        else
        {
            FilteredList = ListItems;
        }
    }
    
    protected void OnPropertyChanged([CallerMemberName] string name = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

XAML:

<StackPanel>
    <TextBox x:Name="txtSearch" PlaceholderText="Search" 
             Text="{Binding SearchText, Mode=TwoWay}" 
             Margin="10"/>
    <ListView x:Name="listView" ItemsSource="{Binding FilteredList}" 
              Margin="10">
        <ListView.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Title}"/>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</StackPanel>

页面代码:

public sealed partial class MainPage : Page
{
    private ListViewModel _viewModel;

    public MainPage()
    {
        this.InitializeComponent();
    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        _viewModel = new ListViewModel();
        DataContext = _viewModel;
    }
}
总结

通过以上步骤,我们成功实现了一个带有搜索栏的列表。其中,ViewModel 类从列表数据中筛选符合条件的数据,视图通过绑定搜索关键字和经过过滤后的数据列表实现搜索功能。这是一种通用的、可扩展的方式,适用于各种数据列表场景。