0

As the title suggests, I find myself in this situation a fair amount and believe I'm doing something wrong. Frequently I want a UI that is constantly updating based on the work of background tasks, but find that the separation between simply trying to update the UI and doing work on the UI thread can be hard to find.

Say I have a simple DependencyObject:

public class TaskItem : DependencyObject
{
    public string Name {get;set;}
    public string Command {get;set;}

    public WorkState State
    {
        get { return (WorkState)GetValue(StateProperty); }
        set { SetValue(StateProperty, value); }
    }

    public static readonly DependencyProperty StateProperty = 
        DependencyProperty.Register("State", typeof(WorkState), 
                                     typeof(TaskItem));
}

These objects are stored in an ObservableCollection, called mTaskItems. On some user event, I want to do some work with these objects:

Task.Run(new Action( () => 
{
   foreach (TaskItem task_item in mTaskItems.Where(n => n.State != 
                                                    WorkState.Executing))
   {
      DoSomeWork(task_item);
   }
}));

I can't check the DependencyProperty State of the TaskItem in the above sample because it's now on a different thread from which owns it.

Is it normal to have dispatchers sprinkled throughout the business logic if you want to update the UI during processing or am I going about this in a completely wrong way?

Should my dependency objects not be used as business data containers at all, but just exist as UI data containers? (if so what's the best design to link them?)

Thanks.

Rohit Vats
  • 79,502
  • 12
  • 161
  • 185
Cuthbert
  • 1,202
  • 1
  • 12
  • 18
  • 3
    `DependencyObject` shouldn't be part of business logic. DP's are supposed to be used for data bindings, animations etc. on view. – Rohit Vats Mar 05 '14 at 18:52
  • Okay, at some point my business logic needs to update the DPs, which would involve dispatchers or some other design. Do you know what the best option is for that? – Cuthbert Mar 05 '14 at 18:53
  • 2
    "Should my dependency objects not be used as business data containers at all?" Exactly! The architectural pattern is called MVVM. You typically have dependency properties in the View only. – Clemens Mar 05 '14 at 18:58
  • Like you mentioned in case DependencyObjects needs to be updated that should be done via Dispatcher associated with those DO's. That's the only way. As Clemens suggested MVVM is a way to go. – Rohit Vats Mar 05 '14 at 18:59
  • You should bind to a ViewModel. What's visible in the view (whether they are Dependency Objects or not) will be updated automatically. It's also the responsibility of the ViewModel to re-query the Model when it does something to the Model to change it. E.g. if there is an "update" in the UI, that would flow into the ViewModel, and at that point the ViewModel needs to be smart enough to go get any data that would be updated by what it's currently doing. – Peter Ritchie Mar 05 '14 at 19:52
  • So, in your case, the ViewModel would somehow cause the Task to be Run, know when it's done, and do something with updated data. – Peter Ritchie Mar 05 '14 at 19:53

1 Answers1

0

I find myself in this situation a fair amount and believe I'm doing something wrong.

I also believe that. You simply have no need to extend the DependencyObject class in your business model... there is rarely any common need to extend this class at all. DependencyObjects and DependencyPropertys are designed for use with UI objects. You can get the same property notification functionality from implementing the INotifyPropertyChanged interface in your model instead.

Is it normal to have dispatchers sprinkled throughout the business logic if you want to update the UI during processing or am I going about this in a completely wrong way?

Now this I would say was exactly what you should do... long running tasks should happen in background threads and when you need to update the UI, you need to use a Dispatcher.

Sheridan
  • 68,826
  • 24
  • 143
  • 183
  • _"when you need to update the UI, you need to use a Dispatcher"_ -- this is not correct, at least not in terms of an explicit use of it. Assuming a "normal" implementation, i.e. using `INotifyPropertyChanged`, WPF will automatically dispatch property-change notifications back to the UI thread. You can simply update the property from whatever thread you want; the binding will update the UI object bound to it in the UI thread. – Peter Duniho Oct 07 '16 at 23:37