INotifyPropertyChanged调用 [英] INotifyPropertyChanged invocations

查看:109
本文介绍了INotifyPropertyChanged调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题与PropertyChanged的实际调用有关
与进入Dispatcher线程有关的事件.我看过一个
各种各样的解决方案.有些人只是说不要改变
属性,如果您不在UI线程上",则其他属性会添加对
的引用 分派到数据对象中,并将所有调用推入该对象中
调度员.

我们想到了一个我实际上未见过的变体
我想把它扔出去看看我们是什么人
失踪了!

基本上,在以上两个选项中,我们认为
第二个是两者中最好的(因为呼叫者没有
担心他在哪个线程上).但是我们不喜欢这个主意
将所有调用推到该调度程序上.我们想出了一个
方案的数量(包括实现属性依赖项),其中
WPF UI元素以外的实体将订阅
PropertyChanged事件.没有理由需要采取行动
UI线程.

相反,我们细分了各个处理程序
一对一地确定是否需要将一个处理程序调用到UI
线程.到目前为止,在各种情况下,每个用户界面
元素数据绑定从DispatcherObject继承.基于此,我们
可以确定a)此特定调用是否需要针对
运行 b)如果是,则针对哪个调度程序.

最终看起来像这样:

 PropertyChangedEventHandler temp = PropertyChanged;
            如果(temp!= null)
            {
                foreach(在temp.GetInvocationList()中删除del)
                {
                    DispatcherObject target = del.Target作为DispatcherObject;
                    如果(目标!=空)
                    {
                        target.Dispatcher.BeginInvoke(del,DispatcherPriority.DataBind,this,
                                                 新的PropertyChangedEventArgs(propName));
                    }
                    别的
                    {
                        del.DynamicInvoke(this,new PropertyChangedEventArgs(propName));
                    }
                }
            } 

我们为什么缺少这是一个不好的主意吗?

谢谢

解决方案

<

    x : =""BackgroundNotify.MainWindow""

    xmlns = http://schemas.microsoft.com/winfx/2006/xaml/presentation

    xmlns : = http://schemas.microsoft.com /winfx/2006/xaml

    标题 ="MainWindow"
   高度
="100"; 宽度 = " 250">

  < 网格

  < TextBlock      文本 =&; { 文本 =顶部"

  Horizo​​ntalAlignment =左" 宽度 ="113" 边距 = "12,16,0,0&" />

  </ 网格

</ 窗口 >

在后面的代码中:

使用 System.ComponentModel ;

使用 System.Threading;

命名空间 BackgroundNotify

{

公共 部分 MainWindow

{

   公共 MainWindow()

   {

      InitializeComponent();

      DataContext = 模型();

   }

   公共 模型 : INotifyPropertyChanged

   {

span style ="color:blue">事件 PropertyChangedEventHandler PropertyChanged;

      公共 字符串文本{ 获取私有 设置; }

      公共 Model()

      {

          线程(更新){IsBackground = true }.Start();

      }

      私有 无效 Update()

      {

          var count = 0;

          同时()

          {          ;        
             ; 线程 .Sleep(1000);

              Text =(++ count).ToString();

              如果(PropertyChanged!= null)
     {
         PropertyChanged( new PropertyChangedEventArgs (文本" ));

       }

   }

}

}

运行该应用程序,您会看到TextBlock很好地更新了
即使从另一个线程引发了PropertyChanged事件.


My question relates to the actual invoking of the PropertyChanged
event as it relates to getting onto the Dispatcher thread.  I've seen a
variety of solutions out there.  Some people just say "don't change
properties if you aren't on the UI thread", others add a reference to
Dispatcher into the data object and push all invocations to that
dispatcher.

We thought of a variant that I haven't actually seen
around, so I wanted to throw this out there to find out what we are
missing!

Basically, of the two options above, we thought the
second was the better of the two (because then the caller does not have
to be worried about what thread he is on).  But we didn't like the idea
of pushing all invocations onto that dispatcher.  We came up with a
number of scenarios (including implementing property dependencies) where
an entity other than a WPF UI element would subscribe to the
PropertyChanged event.  There is no reason that action needs to take up
the UI thread.

Instead, we break down the individual handlers
one-by-one and determine if that one handler needs to be invoked to a UI
thread.  In the various scenarios we have run into so far, each UI
element data-bound inherits from DispatcherObject.  Based on that, we
can determine a) does this particular invocation need to run against a
dispatcher, and b) if so, against what dispatcher.

It ends up looking like this:

            PropertyChangedEventHandler temp = PropertyChanged;
            if (temp != null)
            {
                foreach (Delegate del in temp.GetInvocationList())
                {
                    DispatcherObject target = del.Target as DispatcherObject;
                    if (target != null)
                    {
                        target.Dispatcher.BeginInvoke(del, DispatcherPriority.DataBind, this,
                                                 new PropertyChangedEventArgs(propName));
                    }
                    else
                    {
                        del.DynamicInvoke(this, new PropertyChangedEventArgs(propName));
                    }
                }
            }

Is there a reason we are missing as to why this is a BAD idea?

Thanks,

解决方案

Actually, WPF already marshals events raised by an INotifyPropertyChanged implmentation to the correct Dispatcher
thread. Try this:

In XAML:

<Window

    x:Class="BackgroundNotify.MainWindow"

    xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation

    xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml

    Title="MainWindow"
    Height
="100" Width="250">

  <Grid>

  <TextBlock

      Text="{Binding Text}" VerticalAlignment="Top"

      HorizontalAlignment="Left" Width="113" Margin="12,16,0,0" />

  </Grid>

</Window>

In code behind:

using System.ComponentModel;

using System.Threading;

namespace BackgroundNotify

{

    publicpartialclassMainWindow

    {

        publicMainWindow()

        {

            InitializeComponent();

            DataContext = newModel();

        }

        publicclassModel: INotifyPropertyChanged

        {

            publiceventPropertyChangedEventHandlerPropertyChanged;

            publicstringText { get; privateset; }

            publicModel()

            {

                newThread(Update) {IsBackground = true}.Start();

            }

            privatevoidUpdate()

            {

                varcount = 0;

                while(true)

                {                   
                    Thread.Sleep(1000);

                    Text = (++count).ToString();

                    if(PropertyChanged != null)
                    {
                        PropertyChanged(this, newPropertyChangedEventArgs("Text"));

                    }

                }

            }

        }

    }

}

Run the app and you’ll see the TextBlock updating nicely
even though PropertyChanged event is raised from another thread.


这篇关于INotifyPropertyChanged调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆