I've read many thread posts, articles etc. about binding and the thread affinity of GUI controls. There are some post in which the people don't want to use the Dispatcher
.
I also have a workmate who avoids using the Dispatcher in his code. I asked him for the reason but his answer didn't satisfy me. He said, he don't like such kind of "magic" hidden in a class.
Well I'm a fan of the following class.
public class BindingBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private Dispatcher Dispatcher
{
#if SILVERLIGHT
get { return Deployment.Current.Dispatcher; }
#else
get { return Application.Current.Dispatcher; }
#endif
}
protected void RaisePropertyChanged<T>(Expression<Func<T>> expr)
{
var memberExpr = (MemberExpression)expr.Body;
string property = memberExpr.Member.Name;
var propertyChanged = PropertyChanged;
if (propertyChanged == null) return;
if (Dispatcher.CheckAccess())
propertyChanged.Invoke(this, new PropertyChangedEventArgs(property));
else
Dispatcher.BeginInvoke(() => RaisePropertyChanged(expr));
}
}
Here is the question. Are there any reasons why some people don't want to use such a class? Perhaps I have to reconsider this approach.
You have to admit, there is one strange thing. Dispatcher.CheckAccess()
is excluded from Intellisense. Perhaps they are a bit scary due to this fact.
Regards
EDIT:
Ok, another example. Consider a complex object. The collection as example was perhaps not the best idea.
public class ExampleVm : BindingBase
{
private BigFatObject _someData;
public BigFatObject SomeData
{
get { return _someData; }
set
{
_someData = value;
RaisePropertyChanged(() => SomeData);
}
}
public ExampleVm()
{
new Action(LoadSomeData).BeginInvoke(null, null); //I know - it's quick and dirty
}
private void LoadSomeData()
{
// loading some data from somewhere ...
// result is of type BigFatObject
SomeData = result; // This would not work without the Dispatcher, would it?
}
}
I am also, personally, not against of Dispatcher
in view model classes. I haven't seen any significant problems with it, yet it gives the most flexibility to your code.
But I like the idea of encapsulating the usage of Dispatcher
in the infrastructure code as much as possible. Just like you did with RaisePropertyChanged
method (BTW, in case of RaisePropertyChanged
you don't have to dispatch anything - binding already does it for you; you only have to dispatch changes to collections).
The biggest and the only disadvantage that I see here is unit testing. Things can get tricky when you try to test your logic that involves usage of Dispatcher
. Imagine if you had code something like this in a view model:
private void UpdateMyCollection()
{
IList<ModelData> dataItems = DataService.GetItems();
// Update data on UI
Dispatcher.BeginInvoke(new Action(() => {
foreach (ModelData dataItem in dataItems)
{
MyObservableCollection.Add(new DataItemViewModel(dataItem));
}
}));
}
This kind of code is quite typical when it comes to updating collections from a non-UI thread. Now, how would you write a unit test that tests the logic of adding items to the observable collection? First of all, you will need to mock the Dispatcher
property because Application.Current
is null
during unit test execution. Second of all, how will you mock it? Will you create a special thread that will mimic a UI thread and use the Dispatcher
of that thread? So, this kind of things.
The bottom line is that if you want your code to be unit-test-friendly, you need to think of the way how you will mock the Dispatcher
. This is the only concern.
Update:
The second example you provided WILL work without Dispatcher
(binding will do the trick).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With