Parameterize ValidationRule in WPF - wpf

I've only scraped the surface of validation in WPF and have come across a scenario that is likely fairly common: I have a TextBox whose value needs to be validated against a variable data type, depending on the context. For example, if the context's data type is 'int,' then the TextBox needs to accept only input that can be converted to an Int32.
My first thought was to inherit from the ValidationRule class and to include the context and to use a switch inside the overridden Validate function, but I am unable to bind anything to it since it is not a FrameworkElement.
Any thoughts?

You can expose IDataErrorInfo. This lets you do data validation with complex logic.

Personally I don't like using IDataErrorInfo for something this simple because it requires a gratuitous creation of a ViewModels and a lot of extra code where none should be necessary. It should be as simple as this:
I have a markup extension that allows me to create a binding with custom validation code specfied as a C# expression. This is extremely simple to do, except for the C# parser: Just implement ProvideValue() by constructing a MultiBinding that uses a converter and builds the appropriate validation structure. This allows the validation expression to receive the containing DataContext and the user-specified Binding object in addition to the value being validated.
With this solution coded, you can do something like this:
BoundProperty="{my:ValidatedBinding
Path=SomeProperty,
ValidationExpression = context is TextBox ? (int)value>3 : (int)value<7,
Mode=TwoWay,
Converter=...
You could easily adapt my solution without the C# parser by creating the expression as a lambda in the code-behind and referencing it with x:Static:
public static reaonly Expression myValidatorExpression =
(object value, object context, BindingBase binding) =>
context is TextBox ? (int)value>3 : (int)value<7;
...
ValidationExpression={x:Static local:MyClass.myValidatorExpression}
In general I find this technique easier and clearer than using ViewModels. I still use ViewModels when there is a complex transformation needed, otherwise just pure XAML straight to the business objects layer.
Note that this approach assumes your business objects layer is not tied to any particular the back-end storage layout (eg SQL table structure). If it were, changing the back-end storage would require changing my UI and this would not be desirable either, so a ViewModel would be desirable from that standpoint. But if not, I always prefer to keep it simple and just use straight XAML.

Related

.net WinForms data binding using Lambda instead of property

In my project I have a model and I want to bind the visible state of a label using one of the model properties. I do not want to add another ShowLabel property to the model. I want to be able to write something like this:
label.Bindings.Add("Visible", model, m => m.Name != "Default");
Basically I want to be able to write a lambda expression instead of adding a property to my model. Is this possible?
Yes, you can do this using the Format event of the Binding class. You'll still bind to the property in question, but your Format event handler will return a different value (a bool in this case).
var binding = new Binding("Visible", model, "Name");
binding.Format += (sender, args) => args.Value = (string)args.Value != "Default";
label.DataBindings.Add(binding);
Windows Forms data binding recognizes the ICustomTypeDescriptor interface, which allows an object to decide at runtime which properties it presents to data binding. So if you write an implementation of that, you can tell Windows Forms that you have whatever properties you feel like having, and you can decide how to implement them.
Of course, that may not help - if you wanted to avoid adding a property, you may also want to avoid implementing a fairly complex interface. The obvious solution would be to write a type whose job is to act as the data source and bind to that instead of whichever object you're currently binding to.
Of course, if you do that it's probably then easier just to implement whatever property you were going to implement on that wrapper instead.
In general with databinding, you want to avoid binding directly to some underlying model, precisely because you don't want to have to add things to your model purely for the benefit of the UI. This is why 'separated presentation' is very popular - instead of connecting the model and view directly, you stick something in the middle whose job is to mediate. Some call this a viewmodel, some call it a presenter, but the basic principle is always separation of presentation.
It sounds like you're trying to achieve separate of presentation (which is good) but without introducing an extra type so that this middle layer has somewhere to go. Why not just define a class (or a set of classes) to act as that layer?

viewmodel have to be public. How should I deal with that?

Pretty much it summarizes my problem here:
Double check - does it ever make sense to have internal viewmodel class?
I have controls.DLL and I'd like to keep this custom control bindings and viewmodel's internal. However, this doesn't seem to be possible.
How do you get around that? The only way I see it - don't use bindings..
Why do you have a view model for a custom control? I assume you're assigning the view model object to the DataContext property, but this is almost always a mistake: the DataContext should be available to consumers to use and abuse as they please. Stated another way, what happens if a consumer of your custom control explicitly sets the DataContext? It sounds like your control will stop working and throw a bunch of xaml binding errors.
A custom control is inherently lookless. There is no model or view model, just a view. That view is the .cs file. You supply a default look via your themes/generic.xaml file, but consumers should be able to supply their own template. If you're tying them to a view model, they also need to know how to create a view model instance and all of its dependencies. You've just created highly coupled code. DI containers can loosen the coupling, but that just downgrades the relationship between classes from "coupled" to "related". I say, why do consumers even need to know that information?
A better approach is to provide all of the properties for your control as dependency properties. Then your generic.xaml can provide a control template that uses the more efficient TemplateBinding to bind properties/objects to your control. If you need to populate these dependency properties from a business object, expose another dependency property of type IBusinessObject and set the derived values in that object's PropertyMetaData changed handler. If your IBusinessObject type contains a property which is yet another class which implements INotifyPropertyChanged, you should probably (1) rethink your object graph or (2) create a Bnding object in code using the subclass.
I think following all of the above advice will eliminate the problem about which you're concerned plus the other problems as well. Leave the view models to the UserControls. And yes, this is why custom controls are a MASSIVE headache. Doing them right is fairly involved.
Try protected internal. I suppose this should work. Although I don't think its good idea to have the ViewModel not public at all, cause one of the purposes of it is to be able to define several Views against the same ViewModel, which may come from different assemblies.

Pros and cons of having a WPF specifics in the view model

I'm having trouble deciding what to think about this piece of code:
public SolidColorBrush Brush
{
get { return IsValid ? _validItemBrush : _invalidItemBrush; }
}
It is part of a view model in my current project and as you can imagine, the Brush will be bound to some text elements in the UI, to indicate (in-)validity of other pieces of data, in an otherwise fairly simple and straightforward dialog.
The proponents of this piece of code say that since we're using WPF, we might as well allow for some simple WPF specific constructs in the view model.
The opponents say that this violates Separation of Concerns, as it clearly dictates style which should be taken care of solely by the view.
Please share your arguments, and if you're not happy with the code above, please share your ideas around alternative solutions. (I'm particularly interested in what you have to say about using DataTemplates).
Is it possible that there is one solution that could be considered best practice?
Personally, I would have the two brushes be defined in XAML, and have the controls that use them switch brushes (in xaml) based on the IsValid property. This could be done very easily with DataTriggers, or even a single IValueConverter - the converter could take 2 brushes and a boolean and swap between them fairly easily.
This keeps the business logic presentation-neutral - a "Brush" is very specific to a specific form of presentation, and a pure View choice. Hard-coding this into the ViewModel violates the single responsibility principle as well as is not a clean separation of concerns.
I would very much keep this in the View, and switch based on the IsValid (bound) property that is ViewModel specific.
While there are circumstances where I might use WPF constructs in the view model, this isn't one of them. Here's why:
It's harder to change. If you define brushes as resources and use them in styles, changing your application's color scheme can simply be a matter of loading a different resource dictionary. If you hard-code color values in your view models, you have a lot of different things to change if it turns out your end users need different colors.
It's harder to test. If you want to write a unit test that checks to see if a property is returning the right brush, you have to create a brush in your unit test and compare the values of the two, since it's a reference type.
In many, maybe even most cases, it doesn't make the code simpler or easier to maintain. You're pretty likely to already be using a style (assuming that you are conversant with styles), since they make just about everything in WPF easier. Binding IsValid to brush colors is just a matter of adding a DataTrigger to a style. Which is where anyone maintaining this code would expect to find it.
There are certainly times when I do use WPF constructs in the view model - for instance, long ago stopped wondering if it was problem if a view model exposed a property of type Visibility. Note that none of the above concerns apply to that case.
In cases like yours where it's purely aesthetic I use Triggers or the Visual State Manager to change colors.
Sometimes I do use colors in my ViewModels, but only if its part of my software spec (e.g., the color of the chart displaying a patient's CO2 depends on localization). In that case, I use a Color struct bound property, allowing the View to use the Color for a SolidColorBrush, a GradientStop, or whatever it wants. I initially used a string in #AARRGGBB format to completely remove the WPF dependency but my more seasoned co-workers didn't like that.

Is there a way to follow a binding in code?

If i have a Binding which has a property path and the data source can i execute it in code, to find the value?
The path that i am trying to follow can be quite complicated, including collection lookup and multiple levels.
there is a hack :
create a content control
use BindingOperations.SetBinding()
then retrieve the content
is there a better way?
You can avoid using a ContentControl, and write your own very simple class that derives directly from DependencyObject, and provides a single DependencyProperty, which you can then target with the binding. Aside from that, no, there isn't any better way - binding machinery in WPF is very much tied into the concept of dependency properties, and a binding cannot really be a "free-standing expression" that is just evaluated.

Dependency Property Uses in WPF

I am having a hard time figuring out good reasons for the dependency property. Why the System.Controls.TextBox "Text" property a dependency property and not a normal property? What benefits does it serve being a dependency property?
One of the things I am trying to accomplish is to add a ValidationRules property to my UserControl which will contain other validation rules. Like here:
<customControls:RequiredTextBox.ValidationRules>
<validators:NotNullOrEmptyValidationRule ErrorMessage="FirstName cannot be null or empty"/>
</customControls:RequiredTextBox.ValidationRules>
The problem is that I am not sure if ValidationRules property should be DependencyProperty or just a normal property.
The above code gives the following error:
{"Cannot add element to 'ValidationRules'; the property value is null. Error at object 'LearningWPF.ValidationRules.NotNullOrEmptyValidationRule' in markup file 'LearningWPF;component/addcustomerwindow.xaml' Line 35 Position 66."}
Here is the ValidationRules property:
public static readonly DependencyProperty ValidationRulesProperty =
DependencyProperty.Register("ValidationRules",
typeof (Collection<ValidationRule>), typeof (RequiredTextBox),
new FrameworkPropertyMetadata(null));
public Collection<ValidationRule> ValidationRules
{
get { return (Collection<ValidationRule>)GetValue(ValidationRulesProperty); }
set { SetValue(ValidationRulesProperty, value); }
}
The benefits are primarily two fold:
Firstly a dependency property is only created when it is used, this means the TextBox class can be very efficient, with a low memory footprint since it has a minimal number of real properties taking up space on the heap. This is especially important in WPF where all controls are just collections of more and more specific types. If each of those inner types declared tens of properties to define behaviour and look then a high level control like a button would end up having the size of a class with something in the ballpark of a hundred properties.
Secondly dependency properties can be tied to an object other than the type that they are created for. This allows the case where a control can set a Grid.Column property, which the Grid control can read and use for layout. This means that we don't hundreds of decorator classes supplying tiny pieces of functionality required by other controls. This means that xmal is far more intuitive and readable.
Edited to address the example in your revised question:
While your validation property won't gain much benefit from being a dependency property (basically out of the reasons in all the answers so far I can only really see my comment of memory footprint coming in to play), and it certainly isn't advantageous as it is in the case of the Text property of a text box where you may want to bind it, or change it based on some other input, I would still implement it as a dependency property. My reasoning for this is simple; you don't gain much, but it also doesn't cost you anything - I have never wished I had used a basic property in a custom control whereas when I first started writing them I was constantly upgrading my basic properties to dependencies because I wanted some extra functionality.
Simply put, while the dependency property is more complex to define that a normal property I would still use it as the de facto standard for WPF controls unless there was some good reason to do otherwise. In much the same way as a property is the standard for classes, even though a field is easier to implement.
The primary benefits I would say are:
First-class data binding support.
Clean Attached Property semantics
Property values which "depend".
That last point is key
Before Dependency Properties, having a value have a local value, an animatable value, an overridable value, a styleable value, a templatable value would require the declaration of multiple Properties/Fields/Dictionary entries, as well as complex state+precedence management.
Dependency Properties give you all these features out of the box, while declaring just ONE property.
That being said, in your case, you may not want to declare your ValidationRules as a DependencyProperty if you won't need to take advantage of these features.
If you do, you'll want to have different handling for your collections (non-empty collections for example). In this particular example, I would use Reflector and see how the .NET TextBox implements their validation collections, and see if you can reuse or copy the code.
There's no point re-inventing the wheel unless you're certain your wheel will be better. My personal experience is that my reinvented wheels tend to be missing things ;).
As Martin Harris already pointed out, DependencyProperties can limit the memory footprint by throwing the property values into a dictionary, however this can (and I believe was?) done by MSFT before the advent of DependencyProperties.
Martin also mentions Attached Properties, but those were also available (at least in designer) before the advent of DependencyProperties. The Attached Property implementation using DependencyProperties is much cleaner.
Dependency Properties are required if you want to use binding to populate the value of a property. If it was just a normal property, you wouldn't be able to bind the Text property to a property of your View Model object, for example.

Resources