问题的简短背景: 我正在研究WPF应用程序的UI部分。但是因为我已经完成了我的部分 - 决定尝试实现ListBox过滤功能。
我现在所拥有的是:
<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包含搜索字符串。 ListBox - 反映数据,按字段Nombre从数据库中选取。
在结束点 - 我想要有工作过滤器,它在ListBox中只显示与TextBox中的字符串匹配的项目。实时。
当然,我明白如果不修改后面的代码就不可能做到。
问题在于,到目前为止,我实现过滤功能的方法都没有成功,主要是因为我还没有理解我在后面的代码中实现了什么。
对此有任何帮助将不胜感激。可以向任何方向发挥作用 - 如果你想生成代码的整个部分(:)) - 如果你对一个平等的,已经解决的问题有一些好的,可理解的参考,你会受到欢迎 - 这也很棒。
更新
好的,我在这个主题上取得了一些非常大的进步。
我关注的是这个例子:http://www.wpf-tutorial.com/listview-control/listview-filtering/
以下是代码:
<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>
这是后码:
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
编译时没有错误。但是当运行并更改TextBox时 - 抛出意外的应用程序错误。 debuger说&#34; NullReferenceException未被用户代码处理。附加信息:对象引用未设置为对象的实例。&#34;
答案 0 :(得分: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.
Here are the working codes (simplified).
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.
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:
Not the best style, but a working one.