如何确保 ViewModel 属性在再次更改其值之前已绑定在视图上?

2024-05-10

有以下情况:ViewModel有一个变化非常快的对象。 (通过不同的线程)

View通过以下方式获悉NotifyPropertyChanged界面,但似乎它的工作速度很慢,并且在视图绑定新值并绘制它之前,它会更改更多次,因此它会丢失一些值。

我也尝试过绑定View然后排队ViewModel could Enqueue it and View可以通过出队进行绘制。

不幸的是又出现了一个问题:之后RaisePropertyChanged(() => queue); View没有被告知它已被更改。

在这种情况下,实施INotifyPropertyChanged界面不起作用。

你有什么主意吗?

的示例代码ViewModel:

public class ExamplaryViewModel
{
    public ExamplaryViewModel()
    {
        Messenger.Default.Register<NotificationMessage<Message>>(this, m => ProcessNotificationMessage(m.Content));
    }    

    public void ProcessNotificationMessage(Message message)
    {   
        MessageOftenBeingChanged = message;
        RaisePropertyChanged(() => MessageOftenBeingChanged );
    }
}

View绑定到MessageOftenBeingChanged.

另一种选择是按照评论中的建议准备快照:

public void ProcessNotificationMessage(Message message)
{
    Messages.Enqueue(message);
    RaisePropertyChanged(() => Messages);
}

View:

<controls:RichTextBoxMonitor Messages="{Binding Messages} 

Control:

public class BindableRichTextBox : RichTextBox
{

    public static readonly DependencyProperty MessagesProperty = DependencyProperty.Register("Messages",
     typeof(ConcurrentQueue<Message>), typeof(BindableRichTextBox ), new FrameworkPropertyMetadata(null, OnQueueChangedChanged));


    public ConcurrentQueue<Message> CyclicMessages
    {
        get { return (ConcurrentQueue<Message>)GetValue(MessagesProperty ); }

        set { SetValue(MessagesProperty , value); }

但不幸的是RaisePropertyChanged()方法不会触发发生的更改。

我计划控制事件OnQueueChangedChanged尝试出列并将项目绘制为段落的新内联。


你可以实施生产者-消费者 http://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem.

看看这个简化版本。

  • RunProducer仅用于测试,就您而言ProcessNotificationMessage将以类似的方式工作。
  • RunConsumer是一种不断检查新消息和设置的方法Message有一些延迟,否则用户将无法读取它。
  • 这只是概念的快速证明,但您可以更好地实现它,例如通过提供方法ShowNextMessage and IsMessageAvailable,然后视图可以决定何时准备好显示新消息并请求它。这将是一个更好的设计。即使用户可以更快地隐藏一些消息,您只需要绑定ShowNextMessage to Click event.
  • 完整源代码 https://dl.dropboxusercontent.com/u/105509493/udostepnione/Messages.zip

    public class MyViewModel : INotifyPropertyChanged
    {
        public ConcurrentQueue<string> Queue { get; set; }
    
        #region Message
    
        private string _message;
    
        public string Message
        {
            get
            {
                return _message;
            }
            set
            {
                if (_message != value)
                {
                    _message = value;
                    OnPropertyChanged();
                }
            }
        }
        #endregion
    
        public MyViewModel()
        {
            Queue = new ConcurrentQueue<string>();
            RunProducer();
            RunConsumer();
        }
    
        public void RunProducer()
        {
            Task.Run(() =>
            {
                int i = 0;
                while (true)
                {
                    if (Queue.Count < 10)
                        Queue.Enqueue("TestTest " + (i++).ToString());
                    else
                        Task.Delay(500).Wait();
                }
            });
        }
    
        public void RunConsumer()
        {
            Task.Run(() =>
            {
                while (true)
                {
                    if (Queue.Count > 0)
                    {
                        string msg = "";
                        if (Queue.TryDequeue(out msg))
                            Message = msg;
                    }
                    else
                    {
                        Task.Delay(500).Wait();
                    }
    
                    Task.Delay(100).Wait();
                }
            });
        }
    
        #region INotifyPropertyChanged
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        public void OnPropertyChanged([CallerMemberName]string propertyName = null)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    
        #endregion
    }
    

如果队列为空,您可以使用ManualResetMonitor以避免不必要的迭代。

对您的代码的备注:
如果可以更改集合,那么出于绑定目的,您应该仅使用ObservableCollection<T>(或者实现的东西INotifyCollectionChanged),因为它跟踪更改并且不会重新加载所有内容。

然而,在您的代码中,应该刷新整个绑定(因为您通知整个集合已更改),但我认为这种机制更智能,它会检查引用是否相等,如果相等则不会发生刷新。将其设置为可能是一个恶作剧null然后回来会刷新它:-)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何确保 ViewModel 属性在再次更改其值之前已绑定在视图上? 的相关文章

  • 在模板类中声明模板友元类时出现编译器错误

    我一直在尝试实现我自己的链表类以用于教学目的 我在迭代器声明中指定了 List 类作为友元 但它似乎无法编译 这些是我使用过的 3 个类的接口 Node h define null Node
  • 调用 McAfee 病毒扫描引擎

    我收到客户的请求 要求使用他们服务器上的 McAfee 病毒扫描将病毒扫描集成到应用程序中 我做了一些调查 发现 McScan32 dll 是主要的扫描引擎 它导出各种看起来有用的函数 我还发现提到了 McAfee Scan Engine
  • C# 异步等待澄清?

    我读了here http blog stephencleary com 2012 02 async and await html that 等待检查等待的看看它是否有already完全的 如果 可等待已经完成 那么该方法将继续 运行 同步
  • 类型中的属性名称必须是唯一的

    我正在使用 Entity Framework 5 并且有以下实体 public class User public Int32 Id get set public String Username get set public virtual
  • 如何在 Cassandra 中存储无符号整数?

    我通过 Datastax 驱动程序在 Cassandra 中存储一些数据 并且需要存储无符号 16 位和 32 位整数 对于无符号 16 位整数 我可以轻松地将它们存储为有符号 32 位整数 并根据需要进行转换 然而 对于无符号 64 位整
  • 随着时间的推移,添加到 List 变得非常慢

    我正在解析一个大约有 1000 行的 html 表 我从一个字符串中添加 10 个字符串 td 每行到一个list td
  • 为什么 GCC 不允许我创建“内联静态 std::stringstream”?

    我将直接前往 MCVE include
  • 访问外部窗口句柄

    我当前正在处理的程序有问题 这是由于 vista Windows 7 中增强的安全性引起的 特别是 UIPI 它阻止完整性级别较低的窗口与较高完整性级别的窗口 对话 就我而言 我想告诉具有高完整性级别的窗口进入我们的应用程序 它在 XP 或
  • WPF 数据绑定到复合类模式?

    我是第一次尝试 WPF 并且正在努力解决如何将控件绑定到使用其他对象的组合构建的类 例如 如果我有一个由两个单独的类组成的类 Comp 为了清楚起见 请注意省略的各种元素 class One int first int second cla
  • VisualStateManager 和生成的转换

    正当我以为我明白的时候VisualStateManager 有些事情证明我错了 我正在使用 WPF 4 并且尝试简单地在鼠标悬停时放大某个项目 并在鼠标离开时将其缩小 我想我只需定义每个状态VisualStateGroup然后指定一个Vis
  • x:将 ViewModel 方法绑定到 DataTemplate 内的事件

    我基本上问同样的问题这个人 https stackoverflow com questions 10752448 binding to viewmodels property from a template 但在较新的背景下x Bind V
  • C 编程:带有数组的函数

    我正在尝试编写一个函数 该函数查找行为 4 列为 4 的二维数组中的最大值 其中二维数组填充有用户输入 我知道我的主要错误是函数中的数组 但我不确定它是什么 如果有人能够找到我出错的地方而不是编写新代码 我将不胜感激 除非我刚去南方 我的尝
  • 如何在当前 Visual Studio 主机内的 Visual Studio 扩展中调试使用 Roslyn 编译的代码?

    我有一个 Visual Studio 扩展 它使用 Roslyn 获取当前打开的解决方案中的项目 编译它并从中运行方法 程序员可以修改该项目 我已从当前 VisualStudioWorkspace 成功编译了 Visual Studio 扩
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • 使用特定参数从 SQL 数据库填充组合框

    我在使用参数从 sql server 获取特定值时遇到问题 任何人都可以解释一下为什么它在 winfom 上工作但在 wpf 上不起作用以及我如何修复它 我的代码 private void UpdateItems COMBOBOX1 Ite
  • 为什么C++代码执行速度比java慢?

    我最近用 Java 编写了一个计算密集型算法 然后将其翻译为 C 令我惊讶的是 C 的执行速度要慢得多 我现在已经编写了一个更短的 Java 测试程序和一个相应的 C 程序 见下文 我的原始代码具有大量数组访问功能 测试代码也是如此 C 的
  • C# 中最小化字符串长度

    我想减少字符串的长度 喜欢 这串 string foo Lorem ipsum dolor sit amet consectetur adipiscing elit Aenean in vehicula nulla Phasellus li
  • 为什么 std::uint32_t 与 uint32_t 不同?

    我对 C 有点陌生 我有一个编码作业 很多文件已经完成 但我注意到 VS2012 似乎有以下语句的问题 typedef std uint32 t identifier 不过 似乎将其更改为 typedef uint32 t identifi
  • 现代编译器是否优化乘以 1 和 -1

    如果我写 template
  • 如何确定 CultureInfo 实例是否支持拉丁字符

    是否可以确定是否CultureInfo http msdn microsoft com en us library system globalization cultureinfo aspx我正在使用的实例是否基于拉丁字符集 我相信你可以使

随机推荐

  • 小数除以小数并得到零

    为什么当我这样做时 select CAST 1 AS DECIMAL 38 28 CAST 1625625 AS DECIMAL 38 28 我得到 0 吗 但是当我得到 0 时 select CAST 1 AS DECIMAL 20 10
  • 对每个元素使用条件的 Numpy 过滤器

    我有一个过滤器表达式如下 feasible agents filter lambda agent agent gt cost task agent agents where agents是一个Python列表 现在 为了提高速度 我尝试使用
  • 如何解析 FeignClient 响应 json 中的蛇形字段?

    我在 Spring Boot Web 应用程序中配置了一个 FeignClient 我在其中调用返回以下对象的外部 api public class Issue private Assignee assignee private Date
  • 如何转置 R markdown 文档中的表格?

    假设我打印一个名为summary table的数据框 如下所示 summary table data frame a c 1 2 3 b c 11 12 13 c c 21 22 23 d c 31 32 33 e c 41 42 43 f
  • 我很难理解 OPTICS 聚类算法中排序的概念

    我很难理解 OPTICS 聚类算法中排序的概念 如果有人对顺序给出逻辑和直观的解释 并解释什么 我将不胜感激res order下面的代码做了什么以及什么是可靠性图 可以通过命令 plot res 获得 library dbscan set
  • 使用 pyobjc 将元数据写入 pdf

    我正在尝试使用以下 python 代码将元数据写入 pdf 文件 from Foundation import from Quartz import url NSURL fileURLWithPath test pdf pdfdoc PDF
  • 不要在最近的应用程序中显示我的应用程序

    我希望当用户在 hdevice 中运行或关闭我的应用程序时 不要在最近的应用程序中显示我的应用程序 我的目的是 用户禁止运行我的应用程序 我很抱歉说得不好 尝试这个 为您的每一个activity android excludeFromRec
  • SwiftUI TabbedView 仅显示第一个选项卡的内容

    我正在尝试建立一个TabbedView使用以下简单代码 TabbedView Text Hello world tabItemLabel Text Hello Text Foo bar tabItemLabel Text Foo 运行时 两
  • 删除最初使用“未知分词器”创建的表?

    我有一个 sqlite3 数据库 错误消息显示 无法删除此数据库中的单个表unknown tokenizer mm 我直接用命令试了一下DROP TABLE tablename 里面最新的SQLiteSpy http www yunqa d
  • 在 QtCreator 中将 OpenCV 2.3 与 Qt 结合使用

    随着 OpenCV 2 3 版本终于发布 我想在我的系统上编译并安装这个最新版本 由于我经常使用 Qt 和 QtCreator 我当然希望能够在我的 Qt 项目中使用它 我已经尝试了几种方法几个小时 但总是出现错误 第一次尝试 使用WITH
  • perf 找不到外部模块符号

    跑步时perf它找到了我的程序的内核符号和符号 但没有找到外部模块符号 我已经编写了一个内核模块 我使用它加载insmod我怎么知道perf也找到它的符号 我正在运行 2 6 37 6 内核 无法升级 我的perf尚不支持矮人选项 但我认为
  • 让 Emacs ansiterm 和 Zsh 更好地发挥作用

    我一直在尝试在 emacs 会话中使用 Zsh 而无需 emacs 重新映射所有 Zsh 键 我发现 ansi term 对此非常有效 但是我仍然遇到一些问题 我输出了很多垃圾字符 我可以用以下方法修复它 Setup proper term
  • 如何在 Python 中获取显示器分辨率?

    获得显示器分辨率的最简单方法是什么 最好是在元组中 我创建了一个PyPI模块 https pypi org project screeninfo 为此原因 pip install screeninfo 代码 from screeninfo
  • Javascript 中的 k 均值聚类实现? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我需要 k means 聚类算法的 Javascript 实现 我只有一维数据 很少超过 100 个项目
  • 检查Web服务是否存在

    有人可以告诉我确定给定 URL 是否存在 Web 服务 ASP NET 的最佳方法吗 我假设一种方法类似于使用 System Net Webclient 发出请求 但我如何确定它是否是有效的 Web 服务以及我应该发出哪种类型的请求 编辑
  • Visual Studio 2008 (C#) 与 SQL Compact Edition 数据库错误:26

    与网络相关或特定于实例的 建立时发生错误 连接到 SQL Server 服务器 未找到或无法访问 验证实例名称是否为 正确并且 SQL Server 是 配置为允许远程 连接 提供商 SQL 网络 接口 错误 26 错误定位 指定服务器 实
  • 从 Symfony2 中的服务重定向

    我有一项查找页面数据的服务 但如果找不到该数据 则应重定向到主页 对于我的一生 我不知道如何在 Sf2 中做到这一点 有很多不同的方法可以使用服务和路由器 但似乎都不起作用 namespace Acme SomeBundle Service
  • Rfc2898DeriveBytes 与密码的 Sha2 哈希生成

    我最近知道使用 SHA256 为加盐密码生成密码哈希 在阅读了一些有关加盐密码和安全性的内容后 我看到rfc2898derivebytes and passwordderivebytes NET 中的类 使用有什么好处吗rfc2898der
  • Rails_admin 中的范围作为过滤器

    我在我的应用程序中使用rails admin 我的模型上有一些范围 以下是一个示例 class User lt ActiveRecord Base scope unconfirmed where confirmed at IS NULL e
  • 如何确保 ViewModel 属性在再次更改其值之前已绑定在视图上?

    有以下情况 ViewModel有一个变化非常快的对象 通过不同的线程 View通过以下方式获悉NotifyPropertyChanged界面 但似乎它的工作速度很慢 并且在视图绑定新值并绘制它之前 它会更改更多次 因此它会丢失一些值 我也尝