Hello i have 3 questions about MVVM Model.
- Isn't there any way to bypass that redundant
PropertyChanged("PropName");
- What is the best way to wrap POCO objects to WPF
INotifyPropertyChanged, IDataErrorInfo
- How should i interact with (WPfWrap开发者_JAVA技巧ers - POCO) inside ViewModel - via casting, or property...
Thanks.
Here are 3 answers:
You find alternatives of raising the PropertyChanged event without passing the “PropName” as string parameter in the .NET community. However, all of them have other drawbacks (e.g. performance).
The best way is to implement INotifyPropertyChanged and IDataErrorInfo directly in the Model. That’s not always possible. If you need to wrap you Model classes then you might have a look at the DataModel concept.
I’m not sure if I understand the last question right but here is an answer. The ViewModel or DataModel should interact with the Model directly. But these classes shouldn’t interact with the View in a direct way. Use interfaces (e.g. IView) for such scenarios.
More information can be found here: WPF Application Framework (WAF)
Yes, you can do this with a Lamdba expression. But this will cost some processor time (made some quick measurements: this approach is around 200 times slower than using the the string constant. Keep this in mind when using the expression on highly frequented POCOs):
private string ExtractPropertyName<T>( Expression<Func<T>> propertyExpresssion ) { if ( propertyExpresssion == null ) { throw new ArgumentNullException( "propertyExpresssion" ); } var memberExpression = propertyExpresssion.Body as MemberExpression; if ( memberExpression == null ) { throw new ArgumentException( "The expression is not a member access expression.", "propertyExpresssion" ); } var property = memberExpression.Member as PropertyInfo; if ( property == null ) { throw new ArgumentException( "The member access expression does not access a property.", "propertyExpresssion" ); } if ( !property.DeclaringType.IsAssignableFrom( this.GetType( ) ) ) { throw new ArgumentException( "The referenced property belongs to a different type.", "propertyExpresssion" ); } var getMethod = property.GetGetMethod( true ); if ( getMethod == null ) { // this shouldn't happen - the expression would reject the property before reaching this far throw new ArgumentException( "The referenced property does not have a get method.", "propertyExpresssion" ); } if ( getMethod.IsStatic ) { throw new ArgumentException( "The referenced property is a static property.", "propertyExpresssion" ); } return memberExpression.Member.Name; } private string myProperty; public string MyProperty { get { return myProperty; } set { myProperty = value; this.RaisePropertyChanged( ( ) => MyProperty ); } } protected void RaisePropertyChanged<T>( Expression<Func<T>> propertyExpression ) { var propertyName = ExtractPropertyName( propertyExpression ); this.RaisePropertyChanged( propertyName ); }
I think you don't have to wrap them (besides creating a coresponding view model). The POCOs are used as model and the interfaces are implemented by the viewmodel.
- This question is obsolete when you don't wrap the POCOs.
On your first question: Have a look at this post
And do a google search
There are many ways (and discussions)
My 2 cents:
First And second
There is also the option to use Dependency properties in your viewmodel. Alot of people doesnt seem to like doing this because they are a part of wpf and have thread affinity (you can only call the dependency property method from the thread that created that perticular object
I personaly have never found this to be a problem since you're view is both dependent on wpf and has thread affinity anyway, so you even if INotifyPropertyChanged is used you still have to fire the PropertyChanged event from the correct thread.
Dependecy properties have built in notification support and does not require wpf to do any reflection, so they are faster for data binding (but slower to set/get albeit on a small time scale)
your scenario might be diffrent than mine, but its someting to look at i think :)
You can use the new feature of .NET 4.5 named "CallerMemberName" to avoid hard-coding the property name.
精彩评论