Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apply similar binding to multiple WPF controls

Apologies in advance if this has already been asked; I have spent a while Googling and searching stack overflow - but can't find a similar question.

I have a WPF window which has many, many data entry controls. All the controls have two way bindings to the view model, and validate using IDataErrorInfo.

An example of one the bindings is given here:

<TextBox >
  <TextBox.Text>
    <Binding Path="Street"  Mode="TwoWay" NotifyOnValidationError="True" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True">
        <Binding.ValidationRules>
            <ExceptionValidationRule />
        </Binding.ValidationRules>
    </Binding>
  </TextBox.Text>
</TextBox>

The only difference between this binding an all the others is the Path.

All my bindings require the validation rule, and the instruction about when to update as there is a lot of cross field validation going on.

My question is - can I apply the same binding to a textbox without all the copy/pasting I am currently having to do for the above example?

I was thinking that maybe I should roll my own subclass of binding to take care of it - but I have no idea if this is good practice or not?

Update: I've just tried a subclass of the binding like so:

 public class ExceptionValidationBinding : Binding
{
    public ExceptionValidationBinding()
    {
        Mode = BindingMode.TwoWay;
        NotifyOnValidationError = true;
        UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
        ValidatesOnDataErrors = true;
        ValidationRules.Add(new ExceptionValidationRule());
    }
}

which makes my xaml look like this:

<TextBox Text="{bindings:ExceptionValidationBinding Path=PostCode}" />

And it seems to work... like I said - no idea if there are any problems with this approach though.

like image 262
Jay Avatar asked Dec 05 '25 03:12

Jay


2 Answers

If you don't want any code in your view's code-behind, you can create a MarkupExtension and use it in your XAML. Here's an example of the MarkupExtension:

public class MyBinding : MarkupExtension
{
    public string ThePath { get; set; }
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        Binding binding = new Binding(ThePath) {
            Mode = BindingMode.TwoWay,
            NotifyOnValidationError = true,
            UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
            ValidatesOnDataErrors = true
        };
        binding.ValidationRules.Add(new ExceptionValidationRule());
        return binding;
    }
}

Then you can do this in your XAML:

<TextBox Text="{local:MyBinding ThePath=Street}">

Edit:Looks like this gives a runtime error. Change the line return binding; to return binding.ProvideValue(serviceProvider);. I guess deriving a class from Binding is actually better, but I will leave this here anyway :)

like image 70
wingerse Avatar answered Dec 07 '25 18:12

wingerse


Even if you're using MVVM, you can apply bindings from the code-behind (as it is still pure-view logic). "Templating" bindings from within XAML, as far as I know, is not possible.

To do it from your code-behind, like so:

void InitBinding() {
    Address bindingSource = ...
    String[] paths = new String[] { "Street", "City", etc... };
    foreach(TextBox textBox in ...) {

        String path = ...  // get the path for this textbox
        Binding binding = new Binding( path );
        binding.Source = bindingSource;
        binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
        BindingOperations.SetBinding( textBox, TextBox.TextProperty, binding );
    }
}
like image 40
Dai Avatar answered Dec 07 '25 19:12

Dai



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!