简体   繁体   English

UWP:通过后台线程的数据绑定更新UI

[英]UWP: Updating UI through data binding from a background thread

I'm using x:Bind (compiled binding) in my UWP app to bind a TextBlock to an integer property in the ViewModel which is converted to a string by a value converter. 我在UWP应用程序中使用x:Bind(编译绑定)将TextBlock绑定到ViewModel中的整数属性,该属性通过值转换器转换为字符串。 I am using a method in the ViewModel on the worker thread to set the properties and call the PropertyChanged event. 我在工作线程上的ViewModel中使用一种方法来设置属性并调用PropertyChanged事件。 However, I am getting an exception (specifically, it's in the XamlBindingSetters class in the MainPage.g.cs file) saying, "The application called an interface that was marshalled for a different thread." 但是,我遇到一个异常(特别是在MainPage.g.cs文件的XamlBindingSetters类中)说,“该应用程序调用了一个编组为另一个线程的接口。” According to this post , this should work just fine in WPF; 根据这篇文章 ,这在WPF中应该可以正常工作; has this ease of functionality been removed in WinRT/UWP or am I doing something wrong? WinRT / UWP中是否消除了这种易用性功能,或者我做错了什么?

Here's exactly what I'm doing. 这正是我在做什么。

My property is defined like this: 我的属性定义如下:

private int myProperty;

    public int MyProperty
    {
        get { return myProperty; }
        set
        {
            Set(ref myProperty, value);
        }
    }

The Set method is part of the Template 10 library and is defined: Set方法是Template 10库的一部分,并且已定义:

public bool Set<T>(ref T storage, T value, [CallerMemberName]string propertyName = null) 
     { 
         if (object.Equals(storage, value)) 
             return false; 
         storage = value; 
         RaisePropertyChanged(propertyName); 
         return true; 
     } 

Nothing wrong there from what I can see; 从我所看到的那里没什么错; it just makes sure the new value is different than the old value and then calls RaisePropertyChanged(propertyName) which makes sure the app is actually running (not in design mode) and then raises the PropertyChanged event. 它只是确保新值不同于旧值,然后调用RaisePropertyChanged(propertyName)来确保应用程序实际上正在运行(不在设计模式下),然后引发PropertyChanged事件。

I set my property from a worker thread: 我从工作线程设置属性:

MyProperty = newValue;

and when it gets to the XamlBindingSetters class: 当它到达XamlBindingSetters类时:

internal class XamlBindingSetters
    {
        public static void Set_Windows_UI_Xaml_Controls_TextBlock_Text(global::Windows.UI.Xaml.Controls.TextBlock obj, global::System.String value, string targetNullValue)
        {
            if (value == null && targetNullValue != null)
            {
                value = targetNullValue;
            }
            obj.Text = value ?? global::System.String.Empty;
        }
    };

it breaks on that last line (obj.Text = ...) and tells me that the application called an interface that was marshalled for a different thread. 它在最后一行(obj.Text = ...)中断,并告诉我该应用程序调用了已编组用于另一个线程的接口。 What am I doing wrong? 我究竟做错了什么?

You need to execute all graphical objects in the UI Thread. 您需要执行UI线程中的所有图形对象。

Typical usage: 典型用法:

obj.Invoke((MethodInvoker) SomeMethod);

See How to Use ISynchronizeInvoke interface? 请参阅如何使用ISynchronizeInvoke接口?

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM