2

There is a similar question(How to pass the UI Dispatcher to the ViewModel anyone provide me some example or full code.I am new to MVVM so I am not getting.

private async void BindMatchGridinAsync()
        {
            await BindMatchGridAsync(); 
        }        
        async Task<ObservableCollection<EfesBet.DataContract.GetMatchDetailsDC>> BindMatchGridAsync()
        {
            await Task.Run(() => 
                {
                    BindMatchGrid();
                });
            return null;
        }
        void BindMatchGrid()
        {
            BindMatchGridDel bindDel = new BindMatchGridDel(BindMatchGridData);
            matchList = new List<GetMatchDetailsDC>();            
            matchList = proxy.GetMatch().ToList();            
            dataGridParent.Dispatcher.BeginInvoke(bindDel, null);
        }
        public delegate void BindMatchGridDel();
        void BindMatchGridData()
        {
            dataGridParent.ItemsSource = matchList;
        }

Now in this code BindMatchGridinAsync() I have put in my constructor of my code behind file(.cs file). It is giving a proper Asynchrous Operation. But I need to implement the same in ViewModel. Kindly suggest me how to implement it. Thanking you in advance.

Community
  • 1
  • 1
Anindya
  • 2,616
  • 2
  • 21
  • 25

5 Answers5

2

You're thinking about this like a WinForms developer, where each control can be on a separate thread.

In WPF there is one UI thread. This thread is called the Dispatcher. So every control will use the same dispatcher.

As mentioned above:

Application.Current.Dispatcher.BeginInvoke(new Action(DoSomething),null);

Is perfectly acceptable and will work with all of your controls because all controls use the application Dispatcher.

Faster Solutions
  • 7,005
  • 3
  • 29
  • 45
  • Solution Thanks for the prompt reply.I have a doubt then in asynchronous operation what is Applicationl.Current ?Many controls might be working (like populating two datagrids,and I have clicked one button) then what is Application.Current? which one will be considered as current? Can you please tell me. – Anindya Aug 30 '13 at 13:01
  • Application.Current accesses the current application object. There is only one application and it's a static object. Both your datagrids would be sharing the Application dispatcher, which processes their update requests in sequence. – Faster Solutions Aug 30 '13 at 13:15
  • Solution Thanks for prompt response. I am giving you my code which is working fine in my code behind in two half as it is not taking in one comment here.private async void BindMatchGridinAsync(){await BindMatchGridAsync();} async Task> BindMatchGridAsync() {await Task.Run(() => { BindMatchGrid();}); return null;} – Anindya Aug 30 '13 at 13:30
  • Solution void BindMatchGrid(){ BindMatchGridDel bindDel = new BindMatchGridDel(BindMatchGridData);matchList = new List(); matchList = proxy.GetMatch().ToList(); dataGridParent.Dispatcher.BeginInvoke(bindDel, null);}public delegate void BindMatchGridDel();void BindMatchGridData() { dataGridParent.ItemsSource = matchList;}Now in this code BindMatchGridinAsync() I have put in my constructor. It is giving a proper Asynchrous Operation. But I need to implement the same in ViewModel. Can you kindly suggest me how to implement it. – Anindya Aug 30 '13 at 13:30
  • I need the Render thread so I can tell the UI thread to wait until the Text on the control has actually been drawn on the screen. Any ideas? – Paul McCarthy Jul 04 '22 at 13:42
0

You don't need to pass dispatcher, in your ViewModel try (WPF version):

Application.Current.Dispatcher.BeginInvoke(new Action(DoSomething),null);
  • that is Application.Current . what I want to know is any control's dispatcher...like dataGridParent.Dispatcher or tbSearch.Dispatcher .. How can I pass these dispatchers to my viewmodel?Thanks for replying me.Please suggest me how to pass tbSearch.Dispatcher or dataGridParent.Dispatcher to ViewModel.Thanking you. – Anindya Aug 30 '13 at 12:29
  • That's a bit iffy, you generally shouldn't pass UI information to ViewModel, that's the whole point of MVVM. If you insist you can for example expose a public property of type Dispatcher in your ViewModel, get the instance of ViewModel in your View code (DataContext as ViewModel or something like that) and set the property, for instance: (DataContext as ViewModel).Dispatcher = textBox.Dispatcher – user1140705 Aug 30 '13 at 12:42
  • Thanks for prompt response. I am giving you my code which is working fine in my code behind.private async void BindMatchGridinAsync() { await BindMatchGridAsync(); } async Task> BindMatchGridAsync() { await Task.Run(() => { BindMatchGrid(); }); return null; } – Anindya Aug 30 '13 at 13:16
  • void BindMatchGrid() { BindMatchGridDel bindDel = new BindMatchGridDel(BindMatchGridData); matchList = new List(); matchList = proxy.GetMatch().ToList(); dataGridParent.Dispatcher.BeginInvoke(bindDel, null); } public delegate void BindMatchGridDel(); void BindMatchGridData() { dataGridParent.ItemsSource = matchList; } – Anindya Aug 30 '13 at 13:17
  • Now in this code BindMatchGridinAsync() I have put in my constructor. It is giving a proper Asynchrous Operation. But I need to implement the same in ViewModel. Can you kindly suggest me how to implement it. it is little large code so I have paste in three comments .kindly take my above 3 comments together to get the code which I am talking here. In this code dataGridParent.Dispatcher.BeginInvoke(bindDel, null); is there and I do not know how to pass this Dispatcher to my ViewModel – Anindya Aug 30 '13 at 13:18
0

With MVVM Light, you can use the DispatcherHelper static class :

// Get the UI dispatcher :
var uiDispatcher = DispatcherHelper.UIDispatcher;
// Execute in UI :
// In current thread
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
    // In UI thread
});
Tonio
  • 743
  • 1
  • 4
  • 18
  • I am glad for your prompt response.I am not using MVVM Light.Can you see my code behind (.cs) code which I have given here in this question.I want to do it in my viewmodel . How can I implement? Can you kindly suggest? – Anindya Aug 30 '13 at 15:13
0

The best solution is to use async and await in a way that does not require a dispatcher at all:

async Task<ObservableCollection<GetMatchDetailsDC>> BindMatchGridAsync()
{
    var matchList = await Task.Run(() => BindMatchGrid());
    dataGridParent.ItemsSource = matchList;
    return new ObservableCollection<GetMatchDetailsDC>(matchList);
}

List<GetMatchDetailsDC> BindMatchGrid()
{
    matchList = new List<GetMatchDetailsDC>();            
    matchList = proxy.GetMatch().ToList();            
    return matchList;
}
Athafoud
  • 2,898
  • 3
  • 40
  • 58
Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • Thanks for the response.I would like to know the code you have given is it for ViewModel? if it is for ViewModel then how can I get dataGridParent.ItemsSource = matchList; in my ViewModel in Function BindMatchGridAsync()?Now if you have provided it for code behind file.Then I would like to say the code which I have provided in my question is already working but yes it is using Dispatcher .But I want it to be in my ViewModel.Can you please suggest? – Anindya Aug 30 '13 at 15:11
  • @AnindyaChatterjee: SO isn't really a good place to learn MVVM by example. I suggest you learn MVVM and data binding, and *then* learn how to do it asynchronously. – Stephen Cleary Aug 30 '13 at 15:31
0

Don't do it! The whole point of using MVVM is to separate your UI implementation from your application logic. If you shove a static call to Application.Current.Dispatcher or similar you are immediately tying your view model to the WPF implementation. How would you test your view model in isolation of WPF?

If you really want to statically access the UI thread then at least use something that abstracts away the fact you are using WPF, like SynchronizationContext:

public class MyViewModel : NotificationObject
{
    private SynchronizationContext _context;

    public MyViewModel()
    {
        _context = SynchronizationContext.Current;
    }
}

Assuming the constructor is called on the UI thread, you now have a private variable that gives you are backdoor to running code on the dispatcher.

Even better, you can register the SynchronizationContext.Current (or an abstraction of it) in your IoC container and have it injected at the constructor. Then you aren't relying on the fact that the UI thread is constructing the view model.

Lawrence
  • 3,287
  • 19
  • 32