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!
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'm not sure what keywords to search for...lost in a sea of Google.
I have a two-way databinding specified between a visual element (slider bar) and a numeric value in my ViewModel. I want to differentiate between when a value change is user-initiated vs ViewModel-based, so that I can selectively trigger an event elsewhere in my application. How can I do this in the code-behind of the XAML file?
Update 2015-02-26: In reply to Amit's question, WHY I need this capability is that I actually have more than one visual element set up for 2-way databinding to the same ViewModel source, so not differentiating leads to an infinite loop (stack overflow) in callbacks to dependent code that itself has the ability update the same values.
Aside - shouldn't there be reputation points for the first time one appropriately ues "stack overflow" on SO?
Your best bet is not to have two different behaviors. You need to fire the same notifications and recalculate the same dependent properties either way. But I've run into cases where, say, sometimes I want to fire off an animation and sometimes I don't, so different behaviors can be necessary.
If you really do need two different behaviors, I would just make two different properties (or a property and a method). Bind one property to the UI, and use the other when you're setting the value programmatically. Give each one the side effects it needs to have.
Not only does this keep things simple, it also means you can write unit tests for both sets of behaviors.
I think the short answer is: not really.
When you bind to a ViewModel property from your XAML element, ultimately the WPF binding system will call the property setter in the ViewModel. Once inside the setter method you have no context as to how you got there. You could possibly check the stack to see where you came from but that would be very brittle code and presumably quite slow as well.
If the property was only being set by either the XAML binding or by the ViewModel, then you could set some kind of Boolean flag in your ViewModel like so:
bool _isBeingSetByVM;
public int Number
{
get { return _number; }
set
{
if (_isBeingSetByVM)
{
// ViewModel has set the property
// Do whatever you need to do...
_isBeingSetByVM = false;
}
if (_number != value)
{
_number = value;
OnPropertyChanged("Number"); // generate PropertyChanged event
}
}
}
int _number;
void SomeMethodInVM()
{
_isBeingSetByVM = true;
Number = 42;
}
But again, this is very brittle code that is hard to maintain. As #Amit says in his comment, the better question might be why you need to do this.
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.
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.
Today, I came across an interesting method of implementing the INotifyPropertyChanged interface. Instead of passing a string name of the property changed, or a lambda expression, we can simply call RaisePropertyChanged(); from the setter, mark that the call is parameterless. This is the code in the RaisePropertyChanged() method:
public virtual void RaisePropertyChanged()
{
var frames = new System.Diagnostics.StackTrace();
for (var i = 0; i < frames.FrameCount; i++)
{
var frame = frames.GetFrame(i).GetMethod() as MethodInfo;
if (frame != null)
if (frame.IsSpecialName && frame.Name.StartsWith("set_"))
{
RaisePropertyChanged(frame.Name.Substring(4));
return;
}
}
throw new InvalidOperationException("NotifyPropertyChanged() can only by invoked within a property setter.");
}
And this is a property that will notify its dependants of its change:
public string MyProperty
{
get { return _myField; }
set
{
_myField= value;
RaisePropertyChanged();
}
}
While I find this approach interesting, I think the performance penalty could be serious in case the property changed often... or if every property in our application used this approach to notify of its change.
I'd like to hear your opinions. (there is no longer the community-wiki checkbox?)
Would this approach be very inefficient?
Source: Article where this approach is presented
I just tested it using this code. (Note that I circumvented the limitation pointed out in Wim Coenen's answer using the MethodImpl attribute. I have my doubts as to whether this is a surefire workaround.)
Results:
Raised event using reflection 1000 times in 25.5334 ms.
Raised event WITHOUT reflection 1000 times in 0.01 ms.
So you can see, the solution involving the stack trace has about 2,500 times the cost of the "normal" solution.
That's the proportional answer, anyway. I personally dislike this idea (clever though it may be) for reasons quite beyond performance issues alone; but, obviously, it's your call.
Edit: For the record, I felt compelled to write a blog post about this—in particular, about the fact that some developers would be tempted to use an approach like this in spite of the performance hit.
Whether you agree with my feelings on the subject or not (I realize that the performance hit is small in absolute terms), I feel that the real killing blow to this idea is that, for it to be even remotely robust, it is necessary to decorate every property setter from which you intend to call RaisePropertyChanged with the MethodImpl attribute, passing MethodImplOptions.NoInlining... which, right there, negates whatever typing savings you otherwise gained.
So you're left with a net loss in development time (by however many seconds it took you to type out the whole MethodImpl attribute part), plus a performance penalty. Very little reason to go this route, if you ask me.
Yeesh, this seems like a lot of work, it'll be slow, and you run the risk of getting the method inlined.
If you want to do this, I'd suggest putting a [MethodImplAttribute] that says not to inline.
My suggestion would be to use a DynamicProxy instead as it'll be much easier and much faster than this approach, the only downside is you must specify the method as virtual. For instance in my work in progress proxy I specify a metaprogramming definition and bind it for my properties, here is my NotifyPropertyChanged interceptor.
private static void SetterInterceptor<T, TProperty>(ProxiedProperty<T, TProperty> property, T target, TProperty value) where T:class,IAutoNotifyPropertyChanged
{
TProperty oldValue;
if (!EqualityComparer<TProperty>.Default.Equals(oldValue = property.GetMethod.CallBaseDelegate(target), value))
{
property.SetMethod.CallBaseDelegate(target, value);
target.OnPropertyChanged(new PropertyChangedEventArgs(property.Property.Name));
}
}
Then it's just a foreach loop across the properties I'm interested in with calls to Delegate.CreateDelegate to perform the binding.
I have no clear proofs, but I believe yes, it would be very costly, especially if every property does this.
Performance doesn't matter, because the linked article states that it doesn't really work:
Apparently this is a method that has
been tried in the past. As Sergey
Barskiy pointed out, the JITter will
likely inline the method and break the
stack frame.
A different approach that I like better is here:
You can get the property name using
reflection on a lambda function that
calls the property getter.
How to raise PropertyChanged event without using string name