DataGrid文本框过滤不起作用
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DataGrid文本框过滤不起作用相关的知识,希望对你有一定的参考价值。
我有DataGrid文本框过滤的问题,因为我改变了我的方式。
有很大的ViewModel
,这个实例是在应用程序初始化期间在MainWindow
中创建的。
public MainWindow()
{
InitializeComponent();
...
viewModel = new ViewModel();
viewModel.Recipients = GetRecipients();
...
}
我不知道这是不是很好的方法,但对我来说这是有效的,所以我坚持这一点。我正在这样做,因为我想在程序启动时从数据库加载一次大数据,所以其他元素可以在整个时间使用它。 GetRecipients
就是用来做的。
这就是我的ViewModel
(重要部分)的样子:
public class ViewModel : INotifyPropertyChanged
{
private ICollectionView recipientsView;
private CultureInfo culture;
private ICommand _command;
private ObservableCollection<Recipient> _recipients;
public ObservableCollection<Recipient> Recipients
{
get { return _recipients; }
set
{
_odbiorcy = value;
OnPropertyChanged("Recipients");
}
}
private bool _isEmpty;
public bool IsEmpty
{
get { return _isEmpty; }
set
{
_isEmpty = value;
OnPropertyChanged("IsEmpty");
}
}
private string _filter;
public string Filter
{
get { return _filter; }
set
{
_filter = value;
recipientsView.Refresh();
OnPropertyChanged("Filter");
}
}
private Recipient_selected;
public Recipient Selected
{
get { return _selected; }
set
{
_selected = value;
OnPropertyChanged("Selected");
}
}
public ViewModel()
{
Recipients = new ObservableCollection<Recipient>();
recipientsView= CollectionViewSource.GetDefaultView(Recipients);
recipientsView.Filter = o => String.IsNullOrEmpty(Filter) ? true : ((Recipient)o).Name.IndexOf(Filter, StringComparison.OrdinalIgnoreCase) >= 0 ||
((Recipient)o).City.IndexOf(Filter, StringComparison.OrdinalIgnoreCase) >= 0 ||
((Recipient)o).Street.IndexOf(Filter, StringComparison.OrdinalIgnoreCase) >= 0 ||
((Recipient)o).PostCode.IndexOf(Filter, StringComparison.OrdinalIgnoreCase) >= 0 ||
((Recipient)o).ContactPerson.IndexOf(Filter, StringComparison.OrdinalIgnoreCase) >= 0;
}
public void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
和...
Recipients.xaml
<UserControl x:Class="DHL.Recipients"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:DHL"
mc:Ignorable="d"
d:DesignHeight="460" d:DesignWidth="750">
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="60" />
<RowDefinition Height="350"/>
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Label Content="Search recipient:" Margin="25,0,0,0"></Label>
<TextBox x:Name="FilterTextBox" Text="{Binding Filter, UpdateSourceTrigger=PropertyChanged}" Width="145" Height="25" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="25,25,0,0"/>
</Grid>
<Grid Grid.Row="1">
<DataGrid IsReadOnly="True" x:Name="RecipientsGrid" AutoGenerateColumns="False" EnableRowVirtualization="True"
EnableColumnVirtualization="True" ItemsSource="{Binding Recipients}" Height="350" VerticalAlignment="Bottom"
SelectedItem="{Binding Selected,Mode=TwoWay}"
HorizontalScrollBarVisibility="Visible" MouseDoubleClick="Row_DoubleClick">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Width="250" Binding="{Binding Name,UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="Street" Width="150" Binding="{Binding Street,UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="House Number" Width="150" Binding="{Binding HouseNumber,UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="Apartament Number" Width="150" Binding="{Binding ApartamentNumber,UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="Postal Code" Width="150" Binding="{Binding PostalCode,UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="City" Width="150" Binding="{Binding City,UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="Contact Person" Width="150" Binding="{Binding ContactPerson, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="Email" Width="150" Binding="{Binding Email, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="Phone Number" Width="150" Binding="{Binding PhoneNumber, UpdateSourceTrigger=PropertyChanged}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
<Grid Grid.Row="2">
<Button x:Name="CloseButton" Click="CloseButton_Click"
VerticalAlignment="Bottom" Margin="0,0,0,10" Width="100" Height="25" Content="Close"></Button>
</Grid>
</Grid>
</Grid>
和Recipients
类:
public partial class Recipients : UserControl
{
ViewModel viewModel;
public Recipients (ViewModel model)
{
InitializeComponent();
this.viewModel = model;
this.DataContext = viewModel;
}
public Recipients ()
{
InitializeComponent();
ViewModel view = new ViewModel();
this.DataContext = view;
}
private void CloseButton_Click(object sender, RoutedEventArgs e)
{
var parent = this.Parent as Window;
if (parent != null)
{
parent.DialogResult = true;
parent.Close();
}
}
private void Row_DoubleClick(object sender, MouseButtonEventArgs e)
{
CloseButton_Click(this, null);
}
}
我试图以两种方式创建新的Recipients
实例(在参数中使用ViewModel
而没有它)。在我改变整个项目之后,两者都停止了工作(创建ViewModel
实例一次并在项目的每个地方使用它 - 还有一部分我还在努力处理)。我认为这可能有用,因为PropertyChanged
但似乎我错了。
问题是:这是创建ViewModel
一次的好方法,而不是在我想要使用的每个UserControl中创建ViewModel
吗?如果是的话,我的代码出了什么问题?
我的代码出了什么问题
你过滤错误的收藏。 这里是最初创建集合及其视图的位置:
public ViewModel()
{
Recipients = new ObservableCollection<Recipient>();
recipientsView= CollectionViewSource.GetDefaultView(Recipients);
// rest of code not shown
}
然后,您要为集合分配新实例:
// MainWindow ctor
viewModel.Recipients = GetRecipients();
您的网格绑定到集合,而不是其视图,集合最终包含GetRecipients
的结果:
ItemsSource="{Binding Recipients}"
要解决此问题,请执行以下操作:
1)修复数据绑定。将网格绑定到集合视图,而不是集合本身:
// view model
public ICollectionView RecipientsView
{
get
{
if (recipientsView == null)
{
// DO NOT create collection view inside constructor
recipientsView = CollectionViewSource.GetDefaultView(Recipients);
recipientsView.Filter = // filtering code here;
}
return recipientsView;
}
}
<!-- DataGrid XAML -->
ItemsSource="{Binding RecipientsView}"
2)让Recipients
得到唯一。通常,您不需要在视图模型中更改集合对象引用。您需要更改收藏内容:
public ObservableCollection<Recipient> Recipients
{
get
{
if (_recipients == null)
{
// DO NOT create collection inside constructor
_recipients = new ObservableCollection<Recipient>();
}
return _recipients;
}
}
3)更改收集人口代码。添加UpdateRecipients
方法来查看模型:
public void UpdateRecipients(IEnumerable<Recipient> newRecipients)
{
Recipients.Clear();
foreach (var item in newRecipients)
{
Recipients.Add(item);
}
}
并在初始化时调用它:
viewModel = new ViewModel();
viewModel.UpdateRecipients(GetRecipients());
以上是关于DataGrid文本框过滤不起作用的主要内容,如果未能解决你的问题,请参考以下文章