I'm a web and backend programmer by nature. Normally I try to avaoid making windows programs. Now I have to make a WPF client.
I have a background task that raises an event every often time. (It is working like a poller and when the criteria are met an event is raised). Noob as I am I wrote this code that was attached to the event to update the UI.
private void IsDisconnectedEvent()
{
UserWindow.Visibility = Visibility.Hidden;
DisconnectWindow.Visibility = Visibility.Visible;
}
This gives an exception because I am not on the same thread. After some googling I found that I should change the code with:
private void IsDisconnectedEvent()
{
Dispatcher.Invoke(() =>
{
UserWindow.Visibility = Visibility.Hidden;
DisconnectWindow.Visibility = Visibility.Visible;
});
}
This works, but this is not the only event and thus makes my code horrible ugly. Are there better ways to do this?
Regarding this:
This works, but this is not the only event and thus makes my code
horrible ugly
Yes, your WPF-based code will definitely be extremely horrible unless you understand and embrace The WPF Mentality.
Basically, all interactions between your custom logic (AKA Business logic or Application Logic) and the WPF UI should manifest in the form of Declarative DataBinding as opposed to the traditional imperative approach.
This means that there should be nothing like this:
UserWindow.Visibility = Visibility.Hidden;
anywhere in your code, simply because introducing things like that makes your code dependent on the UI and thus only executable on the UI thread.
Instead, the WPF approach to that would be to declaratively DataBind the Visibility propety of the UI element (IN XAML) to a relevant bool property that you can operate from the outside, like this:
<UserWindow Visibility="{Binding ShowUserWindow, Converter={my:BoolToVisibilityConverter}}">
<!-- ... -->
</UserWindow>
Then, you would need to create a relevant class that contains the properties the UI is expecting to bind to. This is called a ViewModel.
Notice that in order to properly support Two-Way WPF DataBinding, your ViewModels must Implement the INotifyPropertyChanged interface.
When doing so, it is also convenient to have the PropertyChanged event from that interface marshalled to the UI thread, so that you no longer have to worry about setting the ViewModel's properties by using the Dispatcher.
Therefore our first step is to have all our ViewModels inherit from a class like this:
(taken from this answer):
public class PropertyChangedBase:INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
//Raise the PropertyChanged event on the UI Thread, with the relevant propertyName parameter:
Application.Current.Dispatcher.BeginInvoke((Action) (() =>
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}));
}
}
Once we have our Property Change Notification Dispatch to the UI Thread in place, we can proceed to create a relevant ViewModel that suits, in this case, the UserWindow and it's DataBinding expectations:
public class UserViewModel: PropertyChangedBase
{
private bool _showUserWindow;
public bool ShowUserWindow
{
get {return _showUserWindow; }
set
{
_showUserWindow = value;
OnPropertyChanged("ShowUserWindow"); //This is important!!!
}
}
}
Finally, you would need to set the Window's DataContext to an instance of it's corresponding ViewModel. One simple way to do that is in the Window's constructor:
public UserWindow() //Window's Constructor
{
InitializeComponent(); //this is required.
DataContext = new UserViewModel(); //here we set the DataContext
}
As you can see in this example, there is literally no need to manipulate the UI element's properties in procedural code. This is good not only because it resolves the Thread Affinity issues (because now you can set the ShowUserWindow property from any thread), but also because it makes your ViewModels and logic completely decoupled from the UI and thus testable and more scalable.
This same concept applies to EVERYTHING in WPF.
One detail that I need to mention is that I'm making use of a technique of Combining MarkupExtension and IValueConverter in order to reduce the the XAML boilerplate involved in using Converters.
You can read more about that in the link and also the MSDN DataBinding page linked above.
Let me know if you need further details.
Related
In WPF XAML, I've got a Button's Command property working with an implementation of a class implementing ICommand.
In this implementation, I don't have my CanExecuteChanged event wired up to use CommandManager.RequerySuggested - I want to have control over when CanExecute is called, and using this calls it way more often than necessary.
The only other way I can get ICommand.CanExecute to re-evaluate is to use something like:
public void InvokeCanExecute()
{
CanExecuteChanged.Invoke(this, new EventArgs());
}
In my class implementing the ICommand.
This seems really nasty - am I missing something obvious? I've tried invoking the re-evaluation using PropertyChanged but that doesn't seem to work.
It's true that - if you don't want to use CommandManager.RequerySuggested, which indeed might call CanExecute more often than necessary - you need to explicitly invoke your own InvokeCanExecute method in order to force the command to re-evaluate its CanExecute condition.
However, in most cases the CanExecute condition will depend on public (bindable) properties, meaning properties that raise the PropertyChanged event to indicate that their value has changed - it is possible to hook into this event, in order to automatically call InvokeCanExecute whenever one of the properties the command depends on has changed. For an example of how to implement such a command, see this guy's blog post (if I'm not mistaken, this approach is implemented e.g. as part of the MVVM Light toolkit).
Instantiating a command using this approach would look somewhat like the following:
SaveCommand = new RelayCommand(() => { /* do some stuff; */ },
() => !string.IsNullOrEmpty(Name),
this, () => Name);
Since the command's CanExecute condition (which checks whether Name is empty) depends on the Name property, it needs to be re-evaluated whenever Name's content changes. You simply pass a reference to the Name property to the command's constructor, and InvokeCanExecute will automatically be called whenever the value of Name changes.
In theory, it is possible to go one step further and let the command itself check on which properties it depends - if you're interested in this approach, check out
one of my blog articles, but note that this one heavily depends on reflection so it always depends on the detailed use-case whether this approach is feasible or not. A sample implementation of this solution is included in the MVVMbasics framework (disclaimer: published by me). In this case, you could reduce the command initialization code to:
SaveCommand = CreateRelayCommand(() => { /* do some stuff; */ },
() => !string.IsNullOrEmpty(Name));
No, you are not really missing anything. Here's a similar question that recommends the same approach you're taking: What is the actual task of CanExecuteChanged and CommandManager.RequerySuggested?.
You can make your method a little bit more robust though:
public void InvokeCanExecute()
{
var handler = CanExecuteChanged;
if (handler != null)
{
handler(this, new EventArgs());
}
}
I have a DLL with a class that implement INotifyPropertyChanged.
It has a String Property who's setter trigger PropertyChanged.
This String is modified asynchronously "within" the DLL.
I can but do not wish to modify the behaviour of the DLL since i want to keep it as general and reusable as possible.
If i bind a field in my view to the property it updates fine.
In my Visual Studio solution i wish to keep it as MVVM as possible, not using any polling loops or timers.
What i want to add to the solution is a method that, in the same manner as the field, trigger whenever this property is updated. Is this possible and still keeping it within the MVVM pattern?
INotifyPropertyChanged is an interface that enforces the PropertyChanged event to be implemented. You may simply subscribe to this event to call a method:
MyClass myClass = new MyClass();
myClass.PropertyChanged += myClass_PropertyChanged;
...
public void myClass_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "MyProperty")
DoWork();
}
public void DoWork()
{
//Your functionality.
}
Beeing new at MVVM and WPF, I found myself writing tons of code almost identical in my ViewModel to expose properties and then bind on my WPF controls. Something like this:
private Vendedores _vendedorsel;
public Vendedores VendedorSel
{
get
{
return _vendedorsel;
}
set
{
this._vendedorsel = value;
OnPropertyChanged("VendedorSel");
}
}
Is there a better way to do this, without having so much similar code? maybe something that involves inheritance? Thank you.
You can trim this down a little by using CallerMemberName in your base method, which also make refactoring easier if you ever rename the property:
protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
PropertyChangedEventArgs ea = new PropertyChangedEventArgs(propertyName);
if (PropertyChanged != null)
PropertyChanged(this, ea);
}
This cuts your property code down to:
public Vendedores VendedorSel
{
get
{
return _vendedorsel;
}
set
{
this._vendedorsel = value;
OnPropertyChanged();
}
}
You can get similar gains by using frameworks as mentioned by Geek's answer but still need some amount of the boilerplate in most cases. Aspect oriented programming can be used to inject all this stuff for you onto even auto-properties but that can also be a lot to take on if you're not doing anything else with AOP.
Usually the best thing to make this less painful is some good snippets to generate the boilerplate for you.
I Found an excelent answer to this problem in this great Blog.
I Couldn't understand why I need to fire OnPropertyChanged from every property on every setter and why I can't use an auto-implemented property like this on my ViewModel:
public Vendedores VendedorSel {get; set;}
And the point show in the blog above is that in 95% of cases you can!!!
Why?: Because The only reason to fire OnPropertyChanged is if the property is modify OUTSIDE the scope of the view and to inform to it
"hey! this property change! please update yourself"
But in the majority on cases the property is only Modify within the view! in this case is OnPropertyChange is not need!!
Even more! I could even set a default value for the property on the ViewModel Contructor and still don't need to fire OnPropertyChanged because the contructor is executed BEFORE the binding is made. This whille drastically reduce my code of repetitive unneeded manual defined properties! So Thanks to anybody!
I'm just learning MVVM, and I'm trying to work how to display changes to a calculated property as a result of changes to the values from which it's calculated. All of the solutions I've seen so far seriously violate encapsulation, and I'm wondering whether there's anything better.
Suppose one of the things I need to display is the results of a complex tax calculation. The calculation (and possibly its dependencies) will change from time to time, so I would like to keep it strictly encapsulated.
The solution most often offered here seems to be to get all of the properties on which the tax value depends to invoke PropertyChanged in the ModelView for the property itself and for every property that depends on it. That means that every property needs to know everything that uses or might use it. When my tax rules change in a way that makes the calculation dependent on things it was not previously dependent on, I will need to touch all those new properties that go into my calculation (possibly in other classes, possibly not under my control), to get them to invoke PropertyChanged for the tax value. That completely trashes any hope of encapsulation.
The best solution I can think of is to make the class that does the calculation receive PropertyChanged events, and raise a new PropertyChanged event for the tax value when anything changes that goes into the calculation. That at least preserves encapsulation at class level, but it still breaches method encapsulation: the class shouldn't have to know about how a method does its work.
So, my question is, is there a better way (and if so, what is it)? Or does encapsulation of presentation (MVVM) prevent encapsulation of the business logic? Am I faced with an either/or choice?
The solution most often offered here seems to be to get all of the
properties on which the tax value depends to invoke PropertyChanged in
the ModelView for the property itself and for every property that
depends on it.
No the supporting properties do not need their own change notification unless they are being displayed. But each property will need to call the tax value's OnPropertyChanged("TaxValue") in their setter(s) either directly; or indirectly as per the example below. That way the UI gets updated because a supporting property has changed.
With that said, let us consider an example. One way is to create a method which will do the value calculation. When the ultimate value is set (TaxValue below) it will call OnNotifyPropertyChange. That operation will inform the user of the TaxValue change to the whole world; regardless of what value triggers it (Deduction|Rate|Income):
public class MainpageVM : INotifyPropertyChanged
{
public decimal TaxValue
{
get { return _taxValue; }
set { _taxValue = value; OnPropertyChanged(); } // Using .Net 4.5 caller member method.
}
public decimal Deduction
{
get { return _deduction; }
set { _deduction = value; FigureTax(); }
}
public decimal Rate
{
get { return _rate; }
set { _rate = value; FigureTax(); }
}
public decimal Income
{
get { return _income; }
set { _income = value; FigureTax(); }
}
// Something has changed figure the tax and update the user.
private void FigureTax()
{
TaxValue = (Income - Deduction) * Rate;
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>Raises the PropertyChanged event.</summary>
/// <param name="propertyName">The name of the property that has changed, only needed
/// if called from a different source.</param>
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endif
}
Edit
To use CallerMemberName (and other items) in .Net 4 install the Nuget package:
Microsoft.BCL.
or if not use the standard OnPropetyChanged("TaxValue") instead.
Check out Stephen Cleary's Calculated Properties: https://github.com/StephenCleary/CalculatedProperties
It's very simple and does just this: propagates notifications of dependant properties without polluting the trigger property setter.
Primitive example:
public string Name
{
get { return Property.Get(string.Empty); }
set { Property.Set(value); }
}
public string Greeting => Property.Calculated(() => "Hello, " + Name + "!");
It is incredibly powerful for its size: think Excel-like formula engine for View Model properties.
I used it in several projects both in domain and view model classes, it helped me to eliminate most of imperative control flow (a major source of errors) and make code much more declarative and clear.
The best thing about it is that dependent properties can belong to different view models and dependency graph can change dramatically during runtime and it still just works.
The solution most often offered here seems to be to get all of the properties on which the tax value depends to invoke PropertyChanged in the ModelView for the property itself and for every property that depends on it. ....
Yes, but only for that object: Each property should fire its own property change event in the setter. Additionally the setter should somehow trigger properties that depend on that value on itself. You should not try to trigger updates on other objects proactively: they should listen to this objects PropertyChanged.
The best solution I can think of is to make the class that does the calculation receive PropertyChanged events, and raise a new PropertyChanged event for the tax value when anything changes that goes into the calculation. That at least preserves encapsulation at class level, but it still breaches method encapsulation: the class shouldn't have to know about how a method does its work.
This is indeed the standard way. Each class has the responsibility to monitor the properties that it depends on, and fire property change events for the properties it.
There are probably frameworks that will help to do this for you, but it is worthwhile to know what should happen.
There is an addin called Fody/PropertyChanged that works at compile-time to automatically implement PropertyChanged. It will automatically see what properties in the same class make use of your property and raise all appropriate PropertyChanged events when that one complex tax calculation changes.
You can decompile the compiled code with ILSpy to see what it did and verify that it's raising all appropriate events.
The best solution I can think of is to make the class that does the
calculation receive PropertyChanged events, and raise a new
PropertyChanged event for the tax value when anything changes that
goes into the calculation. That at least preserves encapsulation at
class level, but it still breaches method encapsulation: the class shouldn't have to know about how a method does its work.
I think you're extending the term "encapsulation" to the point of quibbling about syntax. There is no issue here, for instance:
private int _methodXCalls;
public void MethodX() {
Console.WriteLine("MethodX called {0} times", ++_methodXCalls);
}
The field is relevant only within MethodX, but just because the declaration is not syntactically inside MethodX does not mean it breaks method encapsulation.
Likewise, there is no issue with setting up event handlers for each of your properties in the class initialization. As long as it only appears once at initialization, and nothing else is required to "know" that those particular handlers were added, your properties are still logically self-contained. You could probably somehow use attributes on the properties, e.g. [DependsOn(property1, property2)], but this is really just a code readability concern.
In my new WPF Application, I am reusing a Model class. In that model class, all the properties, in their setters, fire NotifyPropertyChanged. In my application, I do not really have a use case of firing INPC for individual property.
I need to know that if I keep the current architecture where individual properties fire INPC every time they get changed, will it cause any performance implications? Does it make sense to have individual properties fire INPC when it is not required?
Generally speaking, anytime you are running a piece of code that you don't have to, you are potentially causing performance issues.
As a rule of thumb, when you write your setters for your properties instead of just setting your backing field and raising the change event, you should check the equality before you notify, thus avoiding unnecessary updates.
for example:
public int MyInteger
{
get { return this._myInteger; }
set {
if ( value != this._myInteger )
{
this._myInteger = value;
RaiseChangedEvent("MyInteger");
}
}
you should also check for attached events in your RaiseChangedEvent methods, so if there are no listeners, you don't throw a null reference exception and you don't unnecessarily make a call:
private void RaiseChangedEvent(string propertyName)
{
var changedHandler = this.PropertyChanged ;
if ( changedHandler != null )
changedHandler(this, new PropertyChangedEventArgs( propertyName ) );
}
When firing the PropertyChanged event, you should have something that looks like:
private void NotifyPropertyChanged(string name) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
If PropertyChanged is null, then there are no listeners attached to your event. So there is minimal, if any, impact on performance.
If there are listeners, then you need the raise the event so they will be notified of changes.
If nothing is attached to the events for those objects, then there shouldn't be much of a performance penalty, though you're still executing code and so there'll be some difference compared to removing it.
INotifyPropertyChange is an event, it fires when there is any changes(changes here means value changes)in property which are binds to controls, ideally it depends on the code written in these event, otherwise it is not a overhead but it is not a good practice to have INotifyPropertyChange for every property of your class