MartinHN
MartinHN

Reputation: 19802

Binding to WPF ViewModel properties

I'm just playing around with WPF and MVVM, and I have made a simple app that displays a Rectangle that changes color whenever Network availability changes.

But when that happens, I get this error: Cannot use a DependencyObject that belongs to a different thread than its parent Freezable.

Code

XAML

<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="400" Width="600">
<DockPanel LastChildFill="True">
    <Rectangle x:Name="networkStatusRectangle" Width="200" Height="200" Fill="{Binding NetworkStatusColor}" />
</DockPanel>
</Window>

Code-behind

using System.Windows; using WpfApplication1.ViewModels;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            DataContext = new NetworkViewModel();
        }
    }
}

ViewModel

using System.ComponentModel;
using System.Net.NetworkInformation;
using System.Windows.Media;

namespace WpfApplication1.ViewModels
{
    public class NetworkViewModel : INotifyPropertyChanged
    {
        private Brush _NetworkStatusColor;

        public Brush NetworkStatusColor
        {
            get { return _NetworkStatusColor; }
            set
            {
                _NetworkStatusColor = value;
                NotifyOfPropertyChange("NetworkStatusColor");
            }
        }

        public NetworkViewModel()
        {
            NetworkChange.NetworkAvailabilityChanged += new NetworkAvailabilityChangedEventHandler(NetworkChange_NetworkAvailabilityChanged);
        }

        protected void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
        {
            if (e.IsAvailable)
            {
                this.NetworkStatusColor = new SolidColorBrush(Colors.Green);
            }
            else
            {
                this.NetworkStatusColor = new SolidColorBrush(Colors.Red);
            }
        }

        public event PropertyChangedEventHandler PropertyChanged = delegate { };

        public void NotifyOfPropertyChange(string propertyName)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

I assume that I should change the NetworkStatusColor property by invoking something?

Upvotes: 0

Views: 5004

Answers (2)

Alex McBride
Alex McBride

Reputation: 7011

With MVVM you have a couple of options when dealing with dispatching. Either you can send some kind of message to your view to have it invoke the operation for you, or you can create some kind of abstract dispatcher service that you are able to easily mock.

Take a look at the MVVM Light toolkit, as it includes a simple dispatcher-service you can use/copy.

Upvotes: 0

Simon P Stevens
Simon P Stevens

Reputation: 27509

You assume correctly. It's the Dispatcher class and the .Invoke method you want to take a look at.

Something a bit like this:

if (this.Dispatcher.Thread != Thread.CurrentThread)
{
    this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(...your method...), any, params, here);
    return
}

There's an MSDN article here with some more info.

Upvotes: 3

Related Questions