【发布时间】:2017-07-27 12:44:47
【问题描述】:
我有一个可以使用文本框过滤的列表视图:
<TextBox TextChanged="txtFilter_TextChanged" Name="FilterLv"/>
在视图代码隐藏中,我执行以下操作:
CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(this.lv.ItemsSource);
view.Filter = UserFilter;
private bool UserFilter(object item)
{
if (String.IsNullOrEmpty(FilterLv.Text))
return true;
else
{
DataModel m = (item as DataModel);
bool result = (m.Name.IndexOf(Filter.Text, StringComparison.OrdinalIgnoreCase) >= 0 ||
//m.Surname.IndexOf(Filter.Text, StringComparison.OrdinalIgnoreCase) >= 0);
return result;
}
}
private void Filter_TextChanged(object sender, TextChangedEventArgs e)
{
CollectionViewSource.GetDefaultView(this.lv.ItemsSource).Refresh();
}
现在我在视图中放置了一个标签,我希望这个标签显示当前在列表视图中显示的项目数。
我该怎么做?我找到了类似this 的东西,但我根本不明白什么是 RowViewModelsCollectionView。在此链接中建议绑定如下:
<Label Content="{Binding ModelView.RowViewModelsCollectionView.Count}"/>
谁能解释我或提供一个非常简单的例子来说明如何做到这一点?
最终更新:
查看模型:
public class TestViewModel
{
// lv is populated later in code
public ObservableCollection<DataModel> lv = new ObservableCollection<DataModel>();
public ObservableCollection<DataModel> LV
{
get
{
return this.lv;
}
private set
{
this.lv= value;
OnPropertyChanged("LV");
}
}
private CollectionView view;
public TestViewModel()
{
this.view = (CollectionView)CollectionViewSource.GetDefaultView(this.LV);
view.Filter = UserFilter;
}
private string textFilter;
public string TextFilter
{
get
{
return this.textFilter;
}
set
{
this.textFilter= value;
OnPropertyChanged("TextFilter");
if (String.IsNullOrEmpty(value))
this.view.Filter = null;
else
this.view.Filter = UserFilter;
}
}
private bool UserFilter(object item)
{
if (String.IsNullOrEmpty(this.TextFilter))
return true;
else
{
DataModel m = (item as DataModel);
bool result = (m.Name.IndexOf(this.TextFilter, StringComparison.OrdinalIgnoreCase) >= 0 ||
//m.Surname.IndexOf(this.TextFilter, StringComparison.OrdinalIgnoreCase) >= 0);
return result;
}
}
/// <summary>
/// Número de registros en la listview.
/// </summary>
public int NumberOfRecords
{
get
{
return this.view.Count;
}
}
}
查看 (xaml):
<!-- search textbox - filter -->
<TextBox TextChanged="txtFilter_TextChanged"
Text="{Binding TextFilter, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
<!-- label to show the number of records -->
<Label Content="{Binding NumberOfRecords}"/>
查看代码隐藏 (xaml.cs):
private void txtFilter_TextChanged(object sender, TextChangedEventArgs e)
{
CollectionViewSource.GetDefaultView((DataContext as TestViewModel).LV).Refresh();
}
当我在搜索文本框中输入并正确更新列表视图时过滤正常,但记录数始终为 0。
我做错了什么?
ATTEMPT2: 下面的另一个尝试不起作用。如果我将我的 listivew 附加到模型视图中声明的视图,则不会显示任何项目。如果我在模型视图中将列表视图附加到 LV,则显示项目,当我通过搜索文本框进行过滤时,它会过滤正常,列表视图已更新,但列表视图中显示的行数始终保持为 0。
注意事项:
- 我使用的是 NET 3.5 Visual Studio 2008。
- 我需要在模型视图中将视图设置为可写,因为我没有设置它 在视图模型构造函数中,我将其设置在 LoadData 方法中 视图模型。 LoadData 从视图代码隐藏构造函数中调用。
查看模型:
namespace MyTest.Example
{
public Class TestViewModel : INotifyPropertyChanged // Implementations not here to simplify the code here.
{
private ObservableCollection<DataModel> lv;
public ObservableCollection<DataModel> LV
{
get
{
return this.lv;
}
private set
{
this.lv = value;
OnPropertyChanged("LV");
}
}
public CollectionView View { get; set; }
public TestViewModel()
{
this.LV = new ObservableCollection<DataModel>();
// this.View = (CollectionView)CollectionViewSource.GetDefaultView(this.LV);
// this.View.Filter = UserFilter;
}
private string textFilter = string.Empty;
public string TextFilter
{
get
{
return this.textFilter ;
}
set
{
this.textFilter = value;
OnPropertyChanged("TextFilter");
this.View.Refresh();
}
}
private bool UserFilter(object item)
{
if (String.IsNullOrEmpty(this.TextFilter))
return true;
else
{
DataModel m = (item as DataModel);
bool result = (m.Name.IndexOf(this.TextFilter, StringComparison.OrdinalIgnoreCase) >= 0 ||
//m.Surname.IndexOf(this.TextFilter, StringComparison.OrdinalIgnoreCase) >= 0);
return result;
}
}
public void LoadData()
{
this.LV = LoadDataFromDB();
this.View = (CollectionView)CollectionViewSource.GetDefaultView(this.LV);
this.View.Filter = UserFilter;
}
} // End Class
} // End namespace
查看代码行为 (xaml.cs):
namespace MyTest.Example
{
public Class TestView
{
public TestView()
{
InitializeComponent();
(DataContext as TestViewModel).LoadData();
}
}
}
查看 (xaml):
xmlns:vm="clr-namespace:MyTest.Example"
<!-- search textbox - filter -->
<TextBox Text="{Binding Path=TextFilter, UpdateSourceTrigger=PropertyChanged}">
<!-- label to show the number of records -->
<Label Content="{Binding Path=View.Count}" ContentStringFormat="No. Results: {0}"/>
<ListView Grid.Row="1" Grid.Column="0" ItemsSource="{Binding Path=View}" SelectionMode="Extended" AlternationCount="2">
尝试 3: 最后我让它工作了。解决方案与 ATTEMPT2 相同,但进行以下更改:
我已经替换了这个:
public CollectionView View { get; set; }
这个:
private CollectionView view;
public CollectionView View {
get
{
return this.view;
}
private set
{
if (this.view == value)
{
return;
}
this.view = value;
OnPropertyChanged("View");
}
}
所有其余部分与 ATTEMPT2 中的相同。在视图 View.Count 中并将 View 作为 ItemsSource 分配给我的列表视图现在一切正常。
【问题讨论】:
-
如标题所述,如果您实际上使用 MVVM 模式,这会容易得多。只需将您的
TextBox绑定到CollectionViewSource.Count。我首先建议将其拟合到实际的 MVVM 模式,或者如果您不想走这条路,请在本地CollectionViewSource上从Count更新TextBox。 -
我正在使用 MVVM,但我完全迷路了。什么是collectionViewSource?我是 WPF 的新手。我的列表视图附加到一个 observablecollection。
-
您发布的代码的第一行使用来自
CollectionViewSource的默认CollectionView,这就是我所指的。 -
抱歉,
Count是CollectionView的属性,而不是CollectionViewSource。你的view变量是CollectionView,所以你可以从那里得到它。 -
@BradleyUffner 但“视图”在视图代码隐藏中,而不是在视图模型中。那么如何在xaml中将其绑定到视图中的标签上呢?
标签: wpf xaml listview collectionviewsource