0

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. I am using a method in the ViewModel on the worker thread to set the properties and call the PropertyChanged event. 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." According to this post, this should work just fine in WPF; has this ease of functionality been removed in WinRT/UWP or am I doing something wrong?

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:

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.

I set my property from a worker thread:

MyProperty = newValue;

and when it gets to the XamlBindingSetters class:

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. What am I doing wrong?

Community
  • 1
  • 1
Owen D.
  • 385
  • 2
  • 3
  • 17
  • 3
    You are updating the UI from the wrong thread. See this question for an answer http://stackoverflow.com/questions/10579027/run-code-on-ui-thread-in-winrt – Ken Tucker Sep 19 '15 at 18:39
  • Okay, thanks. I was hoping that it would be handled automatically like in WPF, but it's not difficult to implement this myself. – Owen D. Sep 19 '15 at 20:10

1 Answers1

1

You need to execute all graphical objects in the UI Thread.

Typical usage:

obj.Invoke((MethodInvoker) SomeMethod);

See How to Use ISynchronizeInvoke interface?

enter image description here

Community
  • 1
  • 1
Denis Voituron
  • 288
  • 1
  • 8
  • Ken Tucker's suggestion is simpler but thanks for the info. – Owen D. Sep 19 '15 at 20:12
  • 3
    MvvmLight? Simply use `Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher.RunAsync` to call the 2nd param function in the UI thread and you're done. No need of a framework which only wraps this code ;) – sibbl Sep 20 '15 at 14:35
  • Yes, but the **DispatcherHelper** class (from MVVM Light) is a helper class for dispatcher operations on the UI thread... for multiple projets: WPF, Univeral Apps, Phone, Xamarin for Android, Xamarin for iOS, etc. – Denis Voituron Sep 20 '15 at 16:06
  • I couldn't reference ISynchronizeInvoke when I tried. Does it even exist in UWP? – Tim Long Nov 10 '15 at 10:08
  • @TimLong [Nope, doesn't exist.](http://stackoverflow.com/questions/33506760/isynchronizeinvoke-missing-in-system-componentmodel) – Owen D. Nov 25 '15 at 00:18