WPF Dispatcher and MVVM

Page 1 of 1

2 Replies - 3510 Views - Last Post: 27 February 2012 - 04:06 PM Rate Topic: -----

#1 The Architect 2.0  Icon User is offline

  • D.I.C Regular

Reputation: 37
  • View blog
  • Posts: 351
  • Joined: 22-May 08

WPF Dispatcher and MVVM

Posted 24 February 2012 - 02:22 AM

Just a quick little question: When developing a WPF MVVM application, is there any situation where you would use the Dispatcher?

I haven't actually used the Dispatcher before, but it seems like its only used when your code actually needs to access a Control. However, the MVVM pattern tells me to never reference the view under any circumstance(databinding aside?). That means that the only place I would use the Dispatcher is in the code-behind for animation effects.

Therefore, in a WPF MVVM application, you never use the dispatcher and, in my case, I shouldn't take the time to learn about it at the moment?

The only time I could see it being used is to run a method on the VM when the application is idle, although, in that case, you still wouldn't care about being able to reference the UI thread.

Is This A Good Question/Topic? 0
  • +

Replies To: WPF Dispatcher and MVVM

#2 janne_panne  Icon User is offline

  • WinRT Dev
  • member icon

Reputation: 429
  • View blog
  • Posts: 1,047
  • Joined: 09-June 09

Re: WPF Dispatcher and MVVM

Posted 24 February 2012 - 03:53 AM

There isn't much to learn in Dispatcher so I would recommend learning it, since it wouldn't take much of your time and might help you later on. Basically it is quite like Invoke method in every control in WinForms.

Quote

The only time I could see it being used is to run a method on the VM when the application is idle, although, in that case, you still wouldn't care about being able to reference the UI thread.


Hmm? Try executing the following code. It has another thread doing all the work which could be the background thread you were talking about:

xaml:
<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <Grid>
		<ListBox ItemsSource="{Binding Path=Items}" />
		<Button Margin="306,183,38,55" Name="Button1" />
	</Grid>
</Window>




code behind:
Imports System.Collections.ObjectModel

Class MainWindow

    Private viewmodel As ViewModel

    Public Sub New()

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        viewmodel = New ViewModel
        Me.DataContext = viewmodel

    End Sub

    Private Sub Button1_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles Button1.Click
        viewmodel.FillItemsAsync()
    End Sub
End Class

Public Class ViewModel

    Public Sub New()
        Me.Items = New ObservableCollection(Of String)
    End Sub

    Public Sub FillItemsAsync()
        Dim thread As New System.Threading.Thread(Sub()
                                                      For index = 1 To 10
                                                          Me.Items.Add("my new item #" & index)
                                                      Next
                                                  End Sub)
        thread.Start()
    End Sub

    Private _Items As ObservableCollection(Of String)
    Public Property Items() As ObservableCollection(Of String)
        Get
            Return _Items
        End Get
        Set(ByVal value As ObservableCollection(Of String))
            _Items = value
        End Set
    End Property

End Class



You should receive error: "This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread."

So you need some kind of a reference to the UI thread. What I usually do is I take System.Threading.SynchronizationContext of the UI thread and pass it to the viewmodel and use it there:

Imports System.Collections.ObjectModel

Class MainWindow

    Private viewmodel As ViewModel

    Public Sub New()

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        viewmodel = New ViewModel(System.Threading.SynchronizationContext.Current)
        Me.DataContext = viewmodel


    End Sub

    Private Sub Button1_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles Button1.Click
        viewmodel.FillItemsAsync()
    End Sub
End Class

Public Class ViewModel

    Private syncContext As System.Threading.SynchronizationContext

    Public Sub New(syncContext As System.Threading.SynchronizationContext)
        Me.syncContext = syncContext
        Me.Items = New ObservableCollection(Of String)
    End Sub

    Public Sub FillItemsAsync()
        Dim thread As New System.Threading.Thread(Sub()
                                                      For index = 1 To 10
                                                          Me.syncContext.Post(Sub(i)
                                                                                  Me.Items.Add("my new item #" & i.ToString)
                                                                              End Sub, index)
                                                      Next
                                                  End Sub)
        thread.Start()
    End Sub

    Private _Items As ObservableCollection(Of String)
    Public Property Items() As ObservableCollection(Of String)
        Get
            Return _Items
        End Get
        Set(ByVal value As ObservableCollection(Of String))
            _Items = value
        End Set
    End Property

End Class



This works and the VM still remains it's business aspects by not referencing any UI stuff, in theory.

This post has been edited by janne_panne: 24 February 2012 - 07:43 AM

Was This Post Helpful? 4
  • +
  • -

#3 The Architect 2.0  Icon User is offline

  • D.I.C Regular

Reputation: 37
  • View blog
  • Posts: 351
  • Joined: 22-May 08

Re: WPF Dispatcher and MVVM

Posted 27 February 2012 - 04:06 PM

ah....thats the key.

I never realized that modifying the content of the datasource counted as interacting with the control itself.

thanks!
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1