使用 CollectionViewSource 实现 ListView - 不刷新?
我正在设置一个 ListView,其 Source
属性设置为我的一个类的 ivar,称为 Cat
。
每个 Cat
都有一个 Trait
对象的 ObservableCollection
:
private ObservableCollection<Trait> _traits = new ObservableCollection<Trait>();
public ObservableCollection<Trait> Traits
{
get
{
return _traits;
}
}
public void AddTrait(Trait t)
{
_traits.Add(t);
// Is this redundant? Is one better than the other?
this.OnPropertyChanged("_traits");
this.OnPropertyChanged("Traits");
}
public IEnumerator<Object> GetEnumerator()
{
return _traits.GetEnumerator();
}
然后我将 Source
属性分配给这个 >Traits
集合:
this.CollectionViewSource.Source = CurrentCat.Traits;
这可以正常工作,并且 Trait
对象可以正确显示在我的 ListView
中。
问题是,对此基础 _traits
集合的更改不会导致 UI 正确更新。例如,这样:
void AddTraitButton_Click(object sender, RoutedEventArgs e)
{
if (this.CurrentCat != null)
{
this.CurrentCat.AddTrait(new Trait());
}
}
在 UI 中似乎不会立即产生任何效果,但是如果我像这样重置 Source
属性:
var oldSource = this.CollectionViewSource.Source;
this.CollectionViewSource.Source = null;
this.CollectionViewSource.Source = oldSource;
那么 ListView 正确更新。但是,我确信一定有一些东西是我遗漏的,因为我希望 UI 在添加/删除项目时进行更新。
编辑: CollectionViewSource
正在应用于我的 XAML 文件中的 ListView
:
<CollectionViewSource x:Name="CollectionViewSource" x:Key="CollectionViewSource" />
...
<ListView x:Name="ItemListView" ItemsSource="{Binding Source={StaticResource CollectionViewSource}}" ...
I'm working on setting up a ListView whose Source
property is set to an ivar of a class of mine, called Cat
.
Each Cat
has an ObservableCollection
of Trait
objects:
private ObservableCollection<Trait> _traits = new ObservableCollection<Trait>();
public ObservableCollection<Trait> Traits
{
get
{
return _traits;
}
}
public void AddTrait(Trait t)
{
_traits.Add(t);
// Is this redundant? Is one better than the other?
this.OnPropertyChanged("_traits");
this.OnPropertyChanged("Traits");
}
public IEnumerator<Object> GetEnumerator()
{
return _traits.GetEnumerator();
}
And then I'm assigning the Source
property to this Traits
collection:
this.CollectionViewSource.Source = CurrentCat.Traits;
This works properly, and the Trait
objects are properly displayed in my ListView
.
The issue is that changes to this underlying _traits
collection do not cause the UI to update properly. For example, this:
void AddTraitButton_Click(object sender, RoutedEventArgs e)
{
if (this.CurrentCat != null)
{
this.CurrentCat.AddTrait(new Trait());
}
}
Doesn't seem to have any effect immediately in the UI, but if I reset the Source
property like so:
var oldSource = this.CollectionViewSource.Source;
this.CollectionViewSource.Source = null;
this.CollectionViewSource.Source = oldSource;
Then the ListView
updates properly. But, I'm sure there must be something that I'm missing, as I'd like for the UI to update upon the addition/removal of an item.
Edit: The CollectionViewSource
is being applied to the ListView
in my XAML file:
<CollectionViewSource x:Name="CollectionViewSource" x:Key="CollectionViewSource" />
...
<ListView x:Name="ItemListView" ItemsSource="{Binding Source={StaticResource CollectionViewSource}}" ...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我现在似乎找不到它,但我似乎记得绑定到
CollectionViewSource
时遇到一些问题。您是否尝试过直接绑定到CurrentCat.Traits
并在代码隐藏中设置this.DataContext = this
(我假设您在这里没有使用 MVVM)?I can't seem to find it now, but I seem to remember some problem with binding to
CollectionViewSource
. Have you tried binding directly toCurrentCat.Traits
and settingthis.DataContext = this
in the code-behind (I am assuming you aren't using MVVM here)?我相信您不想直接绑定到 CollectionViewSource 并替换其
Source
来强制刷新,而是希望绑定到 CVS 的View
属性......并调用 <更新源集合后,code>CollectionViewSource.Refresh()。
另外,有几点需要注意,因为您似乎对 .NET/WPF 约定相对较新:
this
关键字通常是多余的,除非范围内有另一个具有相同名称的标识符值得探索 MVVM 和相关模式(如果您要在 WPF 中执行任何重要操作);它们帮助您使视图(XAML 对象)尽可能轻便且易于更改。
例如,就您的情况而言,我假设您显示的代码来自包含您的 ListView 的任何 Window 或 UserControl 的隐藏代码。遵循 MVVM 模式将涉及创建一个单独的“ViewModel”类,该类将包含 Traits 集合并通过 CollectionViewSource 公开它(使用 View 属性,正如我所提到的) )。然后,您的 UserControl 将分配一个 ViewModel 实例作为其
DataContext
,并且 ListView 可以绑定到公开的 CollectionView。Rather than binding to the CollectionViewSource directly and replacing its
Source
to force a refresh, I believe you want to bind to the CVS'sView
property......and call
CollectionViewSource.Refresh()
after updating the source collection.Also, a couple notes, since you seem relatively new to .NET/WPF conventions:
this
keyword is usually redundant, unless there is another identifier in scope with the same nameIt's worth exploring the MVVM and related patterns if you'll be doing anything non-trivial in WPF; they help you keep your views (XAML objects) as light and easy-to-change as possible.
In your case, for example, I assume the code you've shown is from the code-behind of whatever Window or UserControl contains your ListView. Following the MVVM pattern would involve creating a separate "ViewModel" class that would contain the
Traits
collection and expose it via aCollectionViewSource
(using the View property, as I've mentioned). Your UserControl would then have an instance of the ViewModel assigned as itsDataContext
, and the ListView could be bound to the exposed CollectionView.您仍然可以专门使用 ObservableCollection。 尽管存在一个问题 - 它不会在 IsInDesignMode 中显示数据。也许将来会有所改善。
You may work exclusively with the ObservableCollection still. Although there is one problem - it would not show the data in IsInDesignMode. Maybe in the future it will improve.