XAML Conditional Binding

I have a DataTrigger bound to a TextBlock style, which is defined as such:

<DataTrigger Binding="{Binding Path=Link, Converter={StaticResource HasContentConverter}}" Value="True"> <Setter Property="TextDecorations" Value="Underline" /> <Setter Property="Cursor" Value="Hand" /> </DataTrigger> 

The problem I am facing is that I have several objects that end up using this style, some of which contain the Link property, and some of them don't. Whenever the system encounters an object that does not do this, it prints this error in the output window:

BindingExpression path error: 'Link' property not found in 'object' '' DataRowView '(HashCode = 53681904)'. BindingExpression: Path = Link; DataItem = 'DataRowView' (HashCode = 53681904); target element is "TextBlock" (Name = ''); target - "NoTarget" (type "Object")

This is the expected behavior, however, I wonder if there is a way to tell the processor in XAML to use it only if the Link property exists (i.e. check the property before trying to bind, or some other method that does not display an error message). Is it possible?

+4
source share
2 answers

So my final solution for this was to have a base DataGrid class that implements this style, minus the “trigger” of the specific Link data. Then I got a new DataGrid class, derived from my base class, with code specifically creating a data trigger:

 Binding binding = new Binding("Link"); binding.Converter = new MDTCommon.Converters.HasContentConverter(); DataTrigger trigger = new DataTrigger(); trigger.Binding = binding; trigger.Value = true; Setter setter1 = new Setter(TextBlock.TextDecorationsProperty, TextDecorations.Underline); Setter setter2 = new Setter(TextBlock.CursorProperty, Cursors.Hand); trigger.Setters.Add(setter1); trigger.Setters.Add(setter2); Style style = FindResource("DefaultStyleInQuestion") as Style; style.Triggers.Add(trigger); 

I managed to use this method because the binding object that had the Link property was used only in my derived DataGrid class.

0
source

Both are out of the box and directly this is not possible.

Out of the box: you can write your own BindingExtension, which will behave as follows: bind if support exists, otherwise ignore it. You can also, khem, disable the binding error message, but of course this is usually not required.

Not directly: you can create an attached attribute of some type, and then set such an attribute instead of setting a binding. Your installer attribute will attach to datacontext changes and inspect objects and visual components as they move and establish a binding or not.

Not directly # 2: you can try to “hierarchize” styles and triggers. As you know, Trigger has a condition. Divide your style into two parts: first, this is a general style that does not need to be "protected", and the second contains functions that depend on the "Blargh" property. Set the first style as standard / normal. Now create a readonly property called "DefinesBlargh" or "HasBlarghDefines" that checks if the datacontext of the target object really has such a property. Now add a trigger to the first style that determines if the styled HasBlarghDefined control is set to true, and in the trigger action ...

... and here is the problem. What to do? You cannot replace the style again with the second part of the style, since it will probably remove the trigger and, in turn, disable the logic (this will be a one-time). Or it may just crash because you are trying to change the style twice in a single update rollout. Actually, I don’t know what will happen, but I smell. Moreover, the transition to the second part simply erases the general things that set up the first part.

So, if it really executes and replaces the style, you will need to make sure that the original startup logic and the rest of the first style are preserved, I would suggest using the “inheritace style”, that is, the -on style-based property: http://wpftutorial.net /StyleInheritance.html That is, do not create two separate parts, but rather create a "base part" with all the usual things and the "specialized part" on which it is based , and adds unsafe additional things. Now dynamically replacing a specialized analogue is a little more reasonable.

Or, if you have some control over the layout, you can get smart: why apply two styles to the same component? Set the general style to some external border of the control and place an additional trigger there, and let the trigger apply a small unsafe second style to the control.

If you really need to aim exactly one control on both parts of the style and cannot use “based on”, or maybe if it just doesn’t work, etc., you can do another smart trick: use MultiStyle , which allows you to define a style that combines two / three / + other styles into one, and then builds a trigger hierarchy as follows:

 multitrigger condition: HasBlarghDefined = TRUE condition: your own data condition setter: set style = multistyle of "generalpart" and "usnafepart" multitrigger condition: HasBlarghDefined = FALSE condition: your own data condition setter: set style = just a generalpart 

IMHO, which just have to work.

edit: forgot about the critical link: MultiStyle

+1
source

All Articles