Binding instances being re-used in DataTemplates when ValidationRules can't be shared
Asked Answered
M

1

6

I'm looking for a solution and/or the rationality behind why a Binding instance is shared within a DataTemplate. This ultimately comes down to the fact that within a DataTemplate, there's seemingly no way to force a new instance of a Binding on a DependencyProperty for each control generated. That is probably a fair and good assumption in all cases except when there are ValidationRules representing something specific about the instance of that control.

To elaborate (I can provide code, but I don't believe it's necessary), I use a DependencyPropertyDescriptor on IsEnabled to update one or more ValidationRules that belong to a TextBox.Text Binding, DatePicker.Text Binding, or a ComboBox.SelectedValue Binding, etc. The idea is that validation will be different or undesired when a control is not enabled.

Because of this, the ValidationRule's state of IsEnabled is specific to the individual control and because the ValidationRule Collection is a part of the Binding and the Binding instance is being shared - each control that ends up sharing that binding will update/override the previous IsEnabled value that was applied by the previously generated control's IsEnabled value.

IsEnabled is only one of at least two properties in the ValidationRule (another custom IsRequired DependencyProperty) that represent the state of the control to which the Binding is applied. When working outside of a DataTemplate (IE: The Binding instance is not shared), this works very well and ignores/alters the validation logic based on the state of the control. I'm not closed off to alternatives but do feel this has been (this issue aside) a very flexible and dynamic option that allows the Binding instance ValidationRule's and the control-changed state of the Rules to evolve effortlessly. This has also allowed me to avoid other obvious but much uglier options such as creating several Bindings, each representing one of the combinations of the ValidationRule's control properties and switching the whole binding out at the time the DependencyPropertyDescriptor fires. shivers

Any thoughts are MUCH appreciated!

Margaritamargarite answered 25/4, 2012 at 23:51 Comment(5)
I had exactly the same issue, and it took me a while to figure out it was the binding that was shared... Have you found any good solution to your question yet? ThanksLongstanding
The only way I found around this was to create a custom binding for each validation/enabled/required scenario, and swap out the bindings when the state of the control changed. This was actually less painful than it sounds and I've had good success with the solution. It just becomes less ideal as the permutation of states increases. You can imagine how messy it could be when you need a custom instance of a binding for each ValidationRule(s)/Enabled/Required combination. My scenario required only about 12 custom bindings. You'll have to let me know if you find something better. Cheers!Margaritamargarite
I've been confronted with this issue in the past too. I also was shocked when I found out the issue with ValidationRules on the Binding instance, and the Binding instance being re-used in a DataTemplate scenario. We have a framework which puts a generic ValidationRule on each binding, and then delegates the actual validation work to external Validation libraries like Enterprise Library validation or anything else.Lifesaving
The solution we came up with, was to set the ValidationStep in our generic ValidationRule to "ValidationStep.UpdatedValue". This way, the BindingExpression (which of course is a different instance for each binding in the DataTemplate scenario), is passed into the ValidationRule. We then further deal with the state from this BindingExpression, which is a unique instance, passing the information to the actual validators. Hope this makes sense. Regards, KoenLifesaving
It does, and that was a great idea and never crossed my mind. We'll have to try this out if or when we revisit the solution in the future. I greatly appreciate the hearing what sounds like a much better alternative!Margaritamargarite
G
1

I suggest you to use x:Shared attribute in the DataTemplate definition.

<DataTemplate x:Key="DataTemplateKey" DataType="{x:Type YourType}" x:Shared="False">
    ...
</DataTemplate>

Since you use it WPF will create a new DataTemplate instance on every request.

Genaro answered 24/1, 2014 at 13:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.