ListBox的实时过滤

时间:2021-06-17 21:29:59

Short background on the problem: I am working on the UI part of an WPF application. But since I have finished my part pretty fast - decided to try implement ListBox filtering function.

关于问题的简短背景:我正在研究WPF应用程序的UI部分。但由于我已经完成了我的部分非常快 - 决定尝试实现ListBox过滤功能。

What I have at this point:

我现在有什么:

    <TextBox Style="{StaticResource WaterMarkMessageTextBoxStyle}" 
             x:Name="usuariosDisponiblesSearch" 
             Grid.Column="1" Grid.Row="1"/>
    <ListBox Style="{StaticResource ListBoxTable}" 
             ItemContainerStyle="{StaticResource AlternatingListViewItemStyle}"                 
             AlternationCount="2" 
             Grid.Column="1" Grid.Row="2" 
             x:Name="lbPossibleContracts" 
             SelectionChanged="lbPossibleContracts_SelectionChanged" >
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Path=Nombre}" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

TextBox contains a searching string. ListBox - reflects data, picked from the DB by field Nombre.

TextBox包含搜索字符串。 ListBox - 反映按字段Nombre从DB中选取的数据。

On the end point - I want to have working filter, which shows in the ListBox only the items, which match with the string in the TextBox. Real time.

在结束点 - 我希望有工作过滤器,它在ListBox中只显示与TextBox中的字符串匹配的项目。即时的。

Of course, I understand that it is impossible to do, without modifying the back code.

当然,我理解如果不修改后面的代码就不可能做到。

The problem is that so far my approaches for implementation of filtering functionality were unsuccessful, mainly because I didn't understood what exactly I am implementing into the back code.

问题是到目前为止,我实现过滤功能的方法都不成功,主要是因为我不明白我在后面的代码中实现了什么。

Any help on this will be appreciated. Works in any direction - if you want produce the whole part of code ( :) ) - you are welcomed, if you have some good, understandable reference to an equal, solved problem -it is great as well.

任何有关这方面的帮助将不胜感激。可以向任何方向发挥作用 - 如果你想生成代码的整个部分(:)) - 如果你对一个平等的,已经解决的问题有一些好的,可理解的参考,你会受到欢迎 - 这也很棒。

UPDATE

UPDATE

Ok, I have made some pretty huge progress in the subject.

好的,我在这个主题上取得了一些非常巨大的进步。

I was following this example: http://www.wpf-tutorial.com/listview-control/listview-filtering/

我跟随这个例子:http://www.wpf-tutorial.com/listview-control/listview-filtering/

Here are the codes:

以下是代码:

        <TextBox Style="{StaticResource WaterMarkMessageTextBoxStyle}" 
             x:Name="usuariosDisponiblesSearch" 
             Grid.Column="1" Grid.Row="1" 
             TextChanged="usuariosDisponiblesSearch_TextChanged" />
        <ListBox  Style="{StaticResource ListBoxTable}"
              ItemContainerStyle="{StaticResource AlternatingListViewItemStyle}"
              AlternationCount="2"
              Margin="0,20,0,0"
              x:Name="lbPossibleContractsFilter" 
              SelectionChanged="lbPossibleContracts_SelectionChanged" >
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Path=Nombre}" />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

And here is the backcode:

这是后码:

public partial class ProjectAssignUsuariosView : UserControl
{
    private ProjectAssignUsuariosViewModel _viewModel;



    public ProjectAssignUsuariosView(Proyecto proyecto)
    {
        InitializeComponent();

        _viewModel = new ProjectAssignUsuariosViewModel(proyecto);

        //TempFilterPart
        lbPossibleContractsFilter.ItemsSource = _viewModel.UsuariosLibres;
        List<Usuario> items = new List<Usuario>();
        filteredUsers.ItemsSource = items;
        CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(lbPossibleContractsFilter.ItemsSource);
        view.Filter = UserFilter;
        //Filtering part ends
    }

    //Filtering
    private bool UserFilter(object item)
    {
        if (String.IsNullOrEmpty(usuariosDisponiblesSearch.Text))
            return true;
        else
            return ((item as Usuario).Nombre.IndexOf(usuariosDisponiblesSearch.Text, StringComparison.OrdinalIgnoreCase) >= 0);
    }


    private void usuariosDisponiblesSearch_TextChanged(object sender, TextChangedEventArgs e)
    {
        CollectionViewSource.GetDefaultView(lbPossibleContractsFilter.ItemsSource).Refresh();
    }
    //Filtering ends

No errors while compiling. But when running and change the TextBox - throws Unexpected application error. And the debuger says "NullReferenceException was unhandled by user code. Additional information: Object reference not set to an instance of an object."

编译时没有错误。但是当运行并更改TextBox时 - 抛出意外的应用程序错误。并且debuger说“NullReferenceException未被用户代码处理。附加信息:对象引用未设置为对象的实例。”

1 个解决方案

#1


0  

Ok, I have made a stable working prototype for described purpose. I was following this example: http://www.wpf-tutorial.com/listview-control/listview-filtering/ The only difference is that my ItemsSource had been placed outside.

好吧,我已经为描述的目的制作了一个稳定的工作原型。我跟随这个例子:http://www.wpf-tutorial.com/listview-control/listview-filtering/唯一的区别是我的ItemsSource被放在了外面。

Here are the working codes (simplified).

这是工作代码(简化)。

XAML:

XAML:

<ListBox Style="{StaticResource ListBoxTable}" 
             ItemContainerStyle="{StaticResource AlternatingListViewItemStyle}"                 
             AlternationCount="2" 
             Grid.Column="1" Grid.Row="2" 
             x:Name="lbPossibleContracts" 
             SelectionChanged="lbPossibleContracts_SelectionChanged" >
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Path=Nombre}" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

Important parts here are the ListBox x:Name Property, which gives access to the ItemsSource. And ListBox SelectionChanged Propert, which calls for refresh of the results.

这里的重要部分是ListBox x:Name Property,它允许访问ItemsSource。和ListBox SelectionChanged属性,它要求刷新结果。

XAML.CS:

XAML.CS:

namespace Todiste.Views.Proyectos
{
public partial class ProjectAssignUsuariosView : UserControl
{
    private ProjectAssignUsuariosViewModel _viewModel;
    public ProjectAssignUsuariosView(Proyecto proyecto)
    {
        InitializeComponent();

        _viewModel = new ProjectAssignUsuariosViewModel(proyecto);

        lbCurrentContracts.ItemsSource = _viewModel.UsuariosProyecto;
        lbPossibleContracts.ItemsSource = _viewModel.UsuariosLibres;
        //Filter Starts            
        CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(lbPossibleContracts.ItemsSource);
        view.Filter = UserFilter;
        //Filter Ends
    }

    //Filter Starts
    private bool UserFilter(object item)
    {
        if (string.IsNullOrEmpty(filter.Text))
            return true;
        else
            return ((item as Usuario).Nombre.IndexOf(filter.Text, StringComparison.OrdinalIgnoreCase) >= 0);
    }

    private void filter_TextChanged(object sender, TextChangedEventArgs e)
    {
        CollectionViewSource.GetDefaultView(lbPossibleContracts.ItemsSource).Refresh();
    }
    // Filter Ends

Here are three main points, worth attention:

以下是三个要点,值得关注:

  1. lbPossibleContracts.ItemsSource = _viewModel.UsuariosLibres; - assigning outside datasource to the list
  2. lbPossibleContracts.ItemsSource = _viewModel.UsuariosLibres; - 将外部数据源分配给列表
  3. Collection view = - defining, the view
  4. 集合视图= - 定义视图
  5. UserFilter and filter_TextChanged - are actually the functions, which are performing filtering and list refreshing actions
  6. UserFilter和filter_TextChanged - 实际上是执行过滤和列表刷新操作的函数

Not the best style, but a working one.

不是最好的风格,而是工作的风格。

#1


0  

Ok, I have made a stable working prototype for described purpose. I was following this example: http://www.wpf-tutorial.com/listview-control/listview-filtering/ The only difference is that my ItemsSource had been placed outside.

好吧,我已经为描述的目的制作了一个稳定的工作原型。我跟随这个例子:http://www.wpf-tutorial.com/listview-control/listview-filtering/唯一的区别是我的ItemsSource被放在了外面。

Here are the working codes (simplified).

这是工作代码(简化)。

XAML:

XAML:

<ListBox Style="{StaticResource ListBoxTable}" 
             ItemContainerStyle="{StaticResource AlternatingListViewItemStyle}"                 
             AlternationCount="2" 
             Grid.Column="1" Grid.Row="2" 
             x:Name="lbPossibleContracts" 
             SelectionChanged="lbPossibleContracts_SelectionChanged" >
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Path=Nombre}" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

Important parts here are the ListBox x:Name Property, which gives access to the ItemsSource. And ListBox SelectionChanged Propert, which calls for refresh of the results.

这里的重要部分是ListBox x:Name Property,它允许访问ItemsSource。和ListBox SelectionChanged属性,它要求刷新结果。

XAML.CS:

XAML.CS:

namespace Todiste.Views.Proyectos
{
public partial class ProjectAssignUsuariosView : UserControl
{
    private ProjectAssignUsuariosViewModel _viewModel;
    public ProjectAssignUsuariosView(Proyecto proyecto)
    {
        InitializeComponent();

        _viewModel = new ProjectAssignUsuariosViewModel(proyecto);

        lbCurrentContracts.ItemsSource = _viewModel.UsuariosProyecto;
        lbPossibleContracts.ItemsSource = _viewModel.UsuariosLibres;
        //Filter Starts            
        CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(lbPossibleContracts.ItemsSource);
        view.Filter = UserFilter;
        //Filter Ends
    }

    //Filter Starts
    private bool UserFilter(object item)
    {
        if (string.IsNullOrEmpty(filter.Text))
            return true;
        else
            return ((item as Usuario).Nombre.IndexOf(filter.Text, StringComparison.OrdinalIgnoreCase) >= 0);
    }

    private void filter_TextChanged(object sender, TextChangedEventArgs e)
    {
        CollectionViewSource.GetDefaultView(lbPossibleContracts.ItemsSource).Refresh();
    }
    // Filter Ends

Here are three main points, worth attention:

以下是三个要点,值得关注:

  1. lbPossibleContracts.ItemsSource = _viewModel.UsuariosLibres; - assigning outside datasource to the list
  2. lbPossibleContracts.ItemsSource = _viewModel.UsuariosLibres; - 将外部数据源分配给列表
  3. Collection view = - defining, the view
  4. 集合视图= - 定义视图
  5. UserFilter and filter_TextChanged - are actually the functions, which are performing filtering and list refreshing actions
  6. UserFilter和filter_TextChanged - 实际上是执行过滤和列表刷新操作的函数

Not the best style, but a working one.

不是最好的风格,而是工作的风格。