标签: observablecollection

我的ViewModel应该有一个ObservableCollection视图还是ViewModels?

我正在尝试通过将DataConmplate绑定到ViewModel上的ObservableCollections来使用ItemsControl来理解基本的MVVM设计方法.

我见过绑定到字符串,视图ViewModel的 ObservableCollections的示例.

绑定到字符串似乎只适用于演示,它是绑定到" 包含ViewModel集合的View集合的ViewModels ",WPF的强大功能似乎真正出现了.

对于那些精通MVVM模式的人来说,将ItemControl,ListView,ListBox绑定到ViewModel中的集合的标准方法是什么?我正在寻找这样的经验建议:

  • 总是使用ObservableCollection <...>而永远不会列出<...>,因为......
  • 比ItemsControl更好的东西来显示一个集合是......
  • 为了使过滤在ViewModel中工作而不是代码隐藏,请使用...
  • 当...时使用View集合和ViewModels集合时......
  • 90%的时间我创建一个ItemsControl并将其绑定到具有自己的ViewModels的ObservableCollection视图...

wpf itemscontrol observablecollection mvvm

11
推荐指数
1
解决办法
4369
查看次数

从CollectionChanged事件处理程序中的ObservableCollection中删除项

我希望能够在将一些项目添加到ObservableCollection后拒绝它们.我无法继承ObservableCollection或使用任何类型的视图,所以我似乎只限于使用定义的一个事件处理程序(CollectionChanged)对禁止的项目执行.Remove().如果项目在提升和处理事件之间的短时间内存在,那就没关系了; 这些物品应该不会留在集合中.在CollectionChanged事件处理程序中调用.Remove()似乎不被允许.在运行时.NET抛出InvalidOperationException:

"在CollectionChanged事件期间无法更改ObservableCollection."

我个人认为.NET应该允许我这样做.如果我创建一个无限循环,这是我自己的错误.

我想使用的代码如下:

myCollection.CollectionChanged += (sender, args) =>
{
    if (args.Action == NotifyCollectionChangedAction.Remove)
        return;
    foreach (var itm in myCollection)
    {
        if (itm.name == "Fred")
            myCollection.Remove(itm);
    }
}
Run Code Online (Sandbox Code Playgroud)

我不确定我有什么选择.使用调度程序似乎不起作用.触发另一个事件并将.Remove调用放在另一个处理程序中是另一个想到的选项.

c# observablecollection

11
推荐指数
2
解决办法
4万
查看次数

ObservableCollection:使用多个新项调用OnCollectionChanged

请注意,我正在尝试使用NotifyCollectionChangedAction.Add操作而不是.Reset.后者确实有效,但对于大型集合来说效率不高.

所以我继承了ObservableCollection:

public class SuspendableObservableCollection<T> : ObservableCollection<T>
Run Code Online (Sandbox Code Playgroud)

由于某种原因,这段代码:

private List<T> _cachedItems;
...

    public void FlushCache() {
        if (_cachedItems.Count > 0) {

        foreach (var item in _cachedItems)
            Items.Add(item);

        OnCollectionChanged(new NotifyCollectionChangedEventArgs(
            NotifyCollectionChangedAction.Add, (IList<T>)_cachedItems));
        }
    }
Run Code Online (Sandbox Code Playgroud)

抛出 一个集合添加事件是指不属于集合的项目

这似乎是BCL的一个错误?

我可以在调用OnCollectionChanged之前逐步查看将新项添加到this.Items

刚刚发现了一个惊人的发现.这些方法都不适合我(flush,addrange),因为只有当这个集合绑定到我的Listview时才会触发错误!

TestObservableCollection<Trade> testCollection = new TestObservableCollection<Trade>();
List<Trade> testTrades = new List<Trade>();

for (int i = 0; i < 200000; i++) 
    testTrades.Add(t);

testCollection.AddRange(testTrades); // no problems here.. 
_trades.AddRange(testTrades); // this one is bound to ListView .. BOOOM!!!
Run Code Online (Sandbox Code Playgroud)

总之,ObservableCollection确实支持添加增量列表,但ListView不支持.Andyp想出了一个解决方法,使其适用于下面的CollectionView,但是由于调用了.Refresh(),这与调用OnCollectionChanged(.Reset)没什么不同.

c# generics subclass observablecollection c#-4.0

10
推荐指数
1
解决办法
1万
查看次数

为什么.NET ObservableCollection <T>实现为类而不是接口?

在阅读Observer设计模式时,我注意到它是使用接口实现的.在Java中,java.util.observable实现也是一个类.C#和Java版本不应该使用接口吗?

斯科特

c# design-patterns observablecollection

10
推荐指数
1
解决办法
2859
查看次数

Update an ObservableCollection with a background worker in MVVM

Ok, I recently implemented a background worker to perform saving and loading of data.

However, getting this to work on a save command has proved difficult.

基本上,我的save命令生成一个事件,该事件通知集合视图模型,已添加Item,并且该项应添加到其自己的ObservableCollection中.

此时,我得到通常的异常,说我不能在不同的线程上更新ICollection.我已经尝试创建一个调用的新列表类型Dispatcher.Invoke,但是这仍然会生成相同的异常.

我想知道是否有其他人对如何最好地解决这个问题有任何建议?

所以目前我有一个继承自ObservableCollection的类:

public class ThreadSafeObservableCollection<T> : ObservableCollection<T>
{
    public ThreadSafeObservableCollection(List<T> collection)
        : base(collection)
    {
        dispatcher = Dispatcher.CurrentDispatcher;
        rwLock = new ReaderWriterLock();
    }

    protected override void InsertItem(int index, T item)
    {
        if (dispatcher.CheckAccess())
        {
            if (index > this.Count)
                return;
            LockCookie c = rwLock.UpgradeToWriterLock(-1);
            base.InsertItem(index, item);
            rwLock.DowngradeFromWriterLock(ref c);
        }
        else
        {
            object[] …
Run Code Online (Sandbox Code Playgroud)

c# wpf multithreading observablecollection

10
推荐指数
1
解决办法
8015
查看次数

自定义ObservableCollection <T>或BindingList <T>,支持定期通知

摘要

我有一个快速变化的大型数据集,我希望将其绑定到UI(带有分组的Datagrid).这些变化分为两个层次;

  • 经常在集合中添加或删除项目(单程500秒)
  • 每个项目都有4个属性,在其生命周期中最多可更改5次

数据的特征如下;

  • 该系列共有约5​​000件商品
  • 可以在一秒内添加项目,然后进行5次属性更改,然后将其删除.
  • 项目也可能暂时保持某种临时状态,并应显示给用户.

我遇到问题的关键要求;

  • 用户应该能够通过对象上的任何属性对数据集进行排序

我想做什么;

  • N秒更新一次UI
  • 仅引发相关的NotifyPropertyChangedEvents

如果第1项具有属性状态,该状态从A - > B - > C - > D移动到我需要/仅想要引发一个"状态"改变事件的区间中,A-> D.

我感谢用户不需要每秒更新数千次UI.如果添加了一个项目,其状态已更改并在UI更新之间的N秒窗口内全部删除,则它永远不会访问DataGrid.

数据网格

DataGrid是我用来显示数据的组件.我目前正在使用XCeed DataGrid,因为它提供了简单的动态分组.我没有在情感上投入其中,如果我可以提供一些动态分组选项(其中包括经常更改的属性),那么股票DataGrid会很好.

我的系统中的瓶颈目前是在项目属性发生变化时重新排序所花费的时间

这占用了YourKit Profiler中98%的CPU.

用不同的方式来表达问题

给定两个BindingList/ObservableCollection实例,这些实例最初相同,但第一个列表已经有一系列额外的更新(您可以监听),生成最小的更改集以将一个列表转换为另一个列表.

外部阅读

我需要的是George Tryfonas 的这个ArrayMonitor的等价物,但是通用它来支持添加和删除项目(它们永远不会被移动).

NB我真的很感谢有人编辑问题的标题,如果他们能想到更好的总结.

编辑 - 我的解决方案

XCeed网格将单元格直接绑定到网格中的项目,而排序和分组功能由BindingList上引发的ListChangedEvents驱动.这有点直观,并排除了下面的MontioredBindingList,因为行将在组之前更新.

相反,我自己包装项目,捕获属性更改事件并将其存储在HashSet中,如Daniel建议的那样.这对我很有用,我会定期迭代这些项目并要求他们通知任何更改.

MonitoredBindingList.cs

这是我对绑定列表的尝试,可以轮询更新通知.可能有一些错误,因为它最终对我没用.

它创建一个添加/删除事件队列,并通过列表跟踪更改.ChangeList与基础列表具有相同的顺序,因此在我们通知添加/删除操作后,您可以针对正确的索引引发更改.

/// <summary>
///  A binding list which allows change events to be polled rather than pushed.
/// </summary>
[Serializable]

public class MonitoredBindingList<T> : BindingList<T>
{
    private readonly object publishingLock = …
Run Code Online (Sandbox Code Playgroud)

c# wpf large-data-volumes bindinglist observablecollection

10
推荐指数
1
解决办法
3449
查看次数

有没有可观察的Qt容器类?

我正在寻找在添加或删除项目时发出Qt信号的通用容器/集合类(例如,列表,映射).

我知道标准的Qt容器类没有这样做.有人知道任何有可观察容器的OSS库吗?

我意识到模板和Qt功能存在问题.如果它很容易,我会自己做,而不是寻找现有的.:)

谢谢.

c++ qt observablecollection

10
推荐指数
1
解决办法
1115
查看次数

以编程方式设置ListView.SelectedItem后,箭头键不起作用

我有一个WPF ListView控件,ItemsSource设置为以这种方式创建的ICollectionView:

var collectionView = 
  System.Windows.Data.CollectionViewSource.GetDefaultView(observableCollection);
this.listView1.ItemsSource = collectionView;
Run Code Online (Sandbox Code Playgroud)

...其中observableCollection是复杂类型的ObservableCollection.ListView配置为为每个项目显示复杂类型上的一个字符串属性.

用户可以刷新ListView,此时我的逻辑存储当前所选项的"键字符串",重新填充底层的observableCollection.然后将先前的排序和过滤器应用于collectionView.此时我想"重新选择"在刷新请求之前选择的项目.observableCollection中的项是新实例,因此我比较各自的字符串属性,然后选择匹配的字符串属性.像这样:

private void SelectThisItem(string value)
{
    foreach (var item in collectionView) // for the ListView in question
    {
        var thing = item as MyComplexType;
        if (thing.StringProperty == value)
        {
            this.listView1.SelectedItem = thing;
            return;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这一切都有效.如果选择了第4项,并且用户按下F5,则重构列表,然后选择具有与前4项相同的字符串属性的项.有时这是新的第4项,有时不是,但它提供了" 最不惊讶的行为 ".

当用户随后使用箭头键在ListView中导航时,问题就出现了.刷新后的第一个向上或向下箭头会导致(新)列表视图中的第一个项目被选中,而不管前一个逻辑选择了哪个项目.任何进一步的箭头键按预期工作.

为什么会这样?

这显然违反了"最不惊讶"的规则.我怎么能避免呢?


编辑
进一步搜索,这似乎与未答复的
WPF ListView箭头导航和击键问题描述的相同异常,除了我提供更多细节.

wpf listview observablecollection icollectionview

10
推荐指数
1
解决办法
5783
查看次数

更改集合时WPF Combobox不会更新

我是WPF的新手.

我正在尝试将字符串集合绑定到组合框.

public ObservableCollection<string> ListString {get; set;}
Run Code Online (Sandbox Code Playgroud)

绑定和datacontext设置如下

<Window 
        x:Class="Assignment2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:validators="clr-namespace:Assignment2"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        DataContext="{Binding RelativeSource={RelativeSource Self}, Path=.}">
    <Grid>
        <ComboBox  Height="23" HorizontalAlignment="Left" Margin="109,103,0,0" Name="StringComboBox" VerticalAlignment="Top" Width="120" SelectionChanged="StringComboBox_SelectionChanged">
            <ComboBox.ItemsSource>
                <Binding Path="ListString" BindsDirectlyToSource="True" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"></Binding>
            </ComboBox.ItemsSource>
        </ComboBox>
Run Code Online (Sandbox Code Playgroud)

我发现这种情况正在发生,因为集合正在更新.如果我写

public MainWindow()
        {

            InputString = "";
            ListString = new ObservableCollection<string>();
            ListString.Add("AAA");
            ListString.Add("BBB");
            ListString.Add("CCC");
          InitializeComponent();

        }
Run Code Online (Sandbox Code Playgroud)

它确实有效,但是如果我InitializeComponent()在第一行上面移动如下,则不起作用.

  public MainWindow()
            {
               InitializeComponent();
                InputString = "";
                ListString = new ObservableCollection<string>();
                ListString.Add("AAA");
                ListString.Add("BBB");
                ListString.Add("CCC");                
            }
Run Code Online (Sandbox Code Playgroud)

我该怎么办??

c# wpf binding combobox observablecollection

10
推荐指数
1
解决办法
2万
查看次数

更新ObservableCollection中的项目时更新ItemsControl

问题:

  • 您在视图中声明ItemsControl(或从中派生的控件ItemsControl).
  • 您将ItemsControl.ItemsSource属性绑定到ObservableCollectionViewModel中的a.
  • 当项目被添加到/从中删除时,您的视图会按预期更新ObservableCollection.
  • 但是,当您更改项目中的项目的属性时,视图不会更新ObservableCollection.

背景:

这似乎是许多WPF开发人员遇到的常见问题.有人问过几次:

项目更改时通知ObservableCollection

ObservableCollection没有注意到它中的Item何时发生变化(即使使用INotifyPropertyChanged)

ObservableCollection和Item PropertyChanged

我的实施:

当Item更改时,我尝试在Notify ObservableCollection中实现接受的解决方案.基本思想是PropertyChanged在MainWindowViewModel中为每个项目连接一个处理程序ObservableCollection.更改项目的属性时,将调用事件处理程序,并以某种方式更新视图.

我无法让实现工作.这是我的实施.

的ViewModels:

class ViewModelBase : INotifyPropertyChanged 
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string propertyName = "")
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}
Run Code Online (Sandbox Code Playgroud)

项目视图模型:

class EmployeeViewModel : ViewModelBase
{
    private int _age;
    private string _name;

    public int Age 
    { …
Run Code Online (Sandbox Code Playgroud)

c# wpf itemscontrol observablecollection mvvm

10
推荐指数
1
解决办法
1万
查看次数