WPF: Condition Binding versus Property, XamlParseException using either - wpf

I'm having trouble with a Condition for a MultiTrigger. If I do the following:
<Condition Binding="{Binding RelativeSource={RelativeSource
AncestorType={x:Type ListView}}}" Property="IsEnabled" Value="True"/>
Then I get this exception:
Condition cannot use both Property and Binding. Error at object 'System.Windows.Condition' in markup file
However, when I do the following:
<Condition Binding="{Binding RelativeSource={RelativeSource
AncestorType={x:Type ListView}}, Path=IsEnabled}" Value="True"/>
Then I get this exception:
Must specify both Property and Value for Trigger. Error at object 'System.Windows.Condition' in markup file
What gives? If it matters, here's the entire trigger:
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Binding="{Binding Path=IsSelected}" Value="True"/>
<Condition Binding="{Binding Path=ItemsControl.AlternationIndex}"
Value="0"/>
<Condition Binding="{Binding RelativeSource={RelativeSource
AncestorType={x:Type ListView}}, Path=IsEnabled}"
Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background"
Value="{StaticResource evenSelected}" />
<Setter Property="BorderBrush"
Value="{StaticResource evenSelectedBorder}" />
</MultiTrigger>

The API in this case is confusing. Condition is used for two different types of multi-triggers, and the properties used are different. When using MultiTrigger, you will use the Property and Value properties. When using MultiDataTrigger (which is what you need), you specify a Binding and a Value. So, if you just switch your code to use a MultiDataTrigger, you'll be good to go:
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=IsSelected}" Value="True"/>
<Condition Binding="{Binding Path=ItemsControl.AlternationIndex}"
Value="0"/>
<Condition Binding="{Binding RelativeSource={RelativeSource
AncestorType={x:Type ListView}}, Path=IsEnabled}"
Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="Background"
Value="{StaticResource evenSelected}" />
<Setter Property="BorderBrush"
Value="{StaticResource evenSelectedBorder}" />
</MultiDataTrigger>

Related

Must have non-null value for 'Binding'

I'm trying to use a special binding for comparisons found here and recommended on another question. NEQ is an added operator that just gives the opposite result of EQ. An InvalidOperationException is thrown every time with the message "Must have non-null value for 'Binding'".
I've tried reducing the statements to just {Binding SourceExpanded} in the condition for testing and even that throws the same exception.
Source, SourceExpanded, and SourceCollapsed are all dependency properties defined in the class this style is associated with.
Is the issue, that you can't bind to a dependency property with a null value? And if so, why is the property value not allowed to be null?
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Property="IsExpanded" Value="True"/>
<Condition Binding="{local:ComparisonBinding SourceCollapsed, NEQ, {x:Null}}" Value="{x:Null}"/>
</MultiDataTrigger.Conditions>
<Setter Property="Source" Value="{Binding SourceExpanded}"/>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Property="IsExpanded" Value="False"/>
<Condition Binding="{local:ComparisonBinding SourceCollapsed, NEQ, {x:Null}}" Value="{x:Null}"/>
</MultiDataTrigger.Conditions>
<Setter Property="Source" Value="{Binding SourceCollapsed}"/>
</MultiDataTrigger>
</Style.Triggers>
I know it is kind of late, you must have solved your problem, if not, here is how to solve it.
You need to change
<Condition Property="IsExpanded" Value="True"/> to
<Condition Binding="{Binding IsExpanded, RelativeSource={RelativeSource Self}}" Value="True" />
Building upon Ray's and this answer: for the MultiDataTrigger Condition element, use explicit Binding instead of Property, and define a default value if null, using TargetNullValue. Here is the code:
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsMouseOver, TargetNullValue=''}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="Foreground" Value="Black" />
</MultiDataTrigger>

WPF Multitrigger Can't be null

This is my Multitrigger:
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=Dringlichkeit, RelativeSource={RelativeSource Self}}" Value="Normal"/>
<Condition Property="ItemsControl.AlternationIndex" Value="0"/>
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="LightPink"/>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=Dringlichkeit, RelativeSource={RelativeSource Self}}" Value="Normal"/>
<Condition Property="ItemsControl.AlternationIndex" Value="1"/>
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="Pink"/>
</MultiDataTrigger>
If I use this trigger as a DataTrigger, the binding works.
But I need the AlternationIndex. I thought it was because I was loading the data via SQL, but when I load the style after SQL, I still have the problem that the binding has a NULL value.
From documentation I can read that you should refer to your AlterationIndex like so:
{Binding RelativeSource={RelativeSource Self}, Path=(ItemsControl.AlternationIndex)}
MSDN Doc
HTH

How to multi-trigger on property and binding in wpf style

I have datagrid in my view and I am trying to trigger a style for the DataGridRowHeader so that it has a particular background when both of the following are true:
IsDirty=True (Property on the DataContext of the row)
IsRowSelected=True (Property on the DataGridRowHeader)
How do I write a multi-trigger that triggers for the above paired conditions as my following style code throws InvalidOperationException/{"Must have non-null value for 'Property'."}:
<Style x:Key="DataGridStandardRowHeaderStyle" TargetType="DataGridRowHeader">
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Binding="{Binding IsDirty}" Value="True" />
<Condition Property="IsRowSelected" Value="True" />
</MultiTrigger.Conditions>
<Setter Property="Background" Value="LightYellow" />
</MultiTrigger>
</Style.Triggers>
</Style>
Kindly help me out.
The mistake in my style code finally got across to me and the correct one that now works for me is given below:
<Style x:Key="DataGridStandardRowHeaderStyle" TargetType="DataGridRowHeader">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsDirty}" Value="True" />
<Condition Binding="{Binding IsRowSelected, RelativeSource={RelativeSource Self}}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="LightYellow" />
</MultiDataTrigger>
</Style.Triggers>
</Style>

Combine DataTrigger and Trigger in a MultiDataTrigger

I've seen from some examples that it is possible to combine this kind of trigger:
<Trigger Property="IsMouseOver" Value="True">
With this kind of data trigger :
<DataTrigger Binding="{Binding IsHighlightable}" Value="True" />
By using a MultiDataTrigger like this:
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsMouseOver}" Value="True"/>
<Condition Binding="{Binding IsHighlightable}" Value="True" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="#BF6DBDD1"/>
<Setter Property="Background" Value="{StaticResource SelectedItemBackgroundBrush}"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
However, this does not work with attached properties. This trigger works:
<Trigger Property="UI:TreeViewHelper.IsMouseDirectlyOverItem" Value="True">
But this does not work:
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=UI:TreeViewHelper.IsMouseDirectlyOverItem}" Value="True"/>
<Condition Binding="{Binding IsHighlightable}" Value="True" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="#BF6DBDD1"/>
<Setter Property="Background" Value="{StaticResource SelectedItemBackgroundBrush}"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
Is there a way I could make the trigger work correctly inside the MultiDataTrigger? The IsMouseDirectlyOverItem property was taken from here http://blogs.msdn.com/b/mikehillberg/archive/2006/09/21/mytreeviewhelperismousedirectlyoveritem.aspx.
Thanks
The syntax for attached properties is different:
Path=(UI:TreeViewHelper.IsMouseDirectlyOverItem)
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsHighlightable}" Value="True"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsMouseOver}" Value="True"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="#BF6DBDD1"/>
<Setter Property="Background" Value="{StaticResource SelectedItemBackgroundBrush}"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>

cannot set tooltip in style

I searched and find out I can't set the tooltip in setter.value directly (in a style.xaml file). However I can use static resource to set the tooltip.
My question is, since I need to supply dynamic text for the tooltip, I can't use static resource. How should I do that?
here is my example.
<Style x:Key="ErrorStyleRadius" TargetType="{x:Type FrameworkElement}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding (Validation.HasError), RelativeSource={RelativeSource Mode=Self}}" Value="True"/>
<Condition Binding="{Binding (Validation.Errors), RelativeSource={RelativeSource Mode=Self}, Converter={StaticResource IsError}}" Value="True"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip>
<Label Content="{Binding somePropertyHere}"/>
</ToolTip>
</Setter.Value>
</Setter>
<Setter Property="Validation.ErrorTemplate" Value="{StaticResource ErrorControlTemplateRadiusError}"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding (Validation.HasError), RelativeSource={RelativeSource Mode=Self}}" Value="True"/>
<Condition Binding="{Binding (Validation.Errors), RelativeSource={RelativeSource Mode=Self}, Converter={StaticResource IsWarning}}" Value="True"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors), Converter={StaticResource ValMsg}}"/>
<Setter Property="Validation.ErrorTemplate" Value="{StaticResource ErrorControlTemplateRadiusWarning}"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
</Style>
for usage, i can use as
<textbox style={staticresource ErrorStyleRadius} text={bind name, validationOnDataError=true}/>
Why don't you try this -
<ToolTip x:Key="MyToolTip"
DataContext={Binding PlacementTarget, RelativeSource={RelativeSource Self}}>
<Label Content="{Binding Text}"/>
</ToolTip>
<Style x:Key="ErrorStyleRadius" TargetType="{x:Type FrameworkElement}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding (Validation.HasError), RelativeSource={RelativeSource Mode=Self}}" Value="True"/>
<Condition Binding="{Binding (Validation.Errors), RelativeSource={RelativeSource Mode=Self}, Converter={StaticResource IsError}}" Value="True"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="ToolTip" Value={StaticResource MyToolTip}>
</Setter>
<Setter Property="Validation.ErrorTemplate" Value="{StaticResource ErrorControlTemplateRadiusError}"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
</Style>
You can give the property name in StaticResource. It will update the tooltip dynamically.
Also you can set the tooltip from your style if you want to set the text to Validation.Error like this -
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}" />
</Trigger>

Resources