I know RelativeSource Self binds to the DataContext in scope. That is not what I want. I have a TextBlock and I want to set a trigger which will multibind 2 things. A value from my DataContext/ViewModel which is easy and I have done that. The 2nd value I want is the Text property of the TextBlock. I can't seem to get the syntax at all.
I have this trigger in a TextBlock style.
<Style TargetType="TextBlock"}">
<Setter Property="Margin" Value="10"></Setter>
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource CustomMultiValueConverter}">
<Binding Path="SelectedCategory"></Binding>
<Binding Path="Text" RelativeSource="{RelativeSource Self}"></Binding>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Foreground" Value="Blue"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
You should be able to use a RelativeSource.AncestorType Binding to reach the TextBlock.Text value. Try this:
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Margin" Value="10"></Setter>
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource CustomMultiValueConverter}">
<Binding Path="SelectedCategory"></Binding>
<Binding Path="Text" RelativeSource="{Binding RelativeSource
AncestorType={x:Type TextBlock}}" />
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Foreground" Value="Blue"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
Related
I wanted to create a cell style to show errors and a text with the tooltip.
My style in the xaml dictionary file is this:
<Style TargetType="{x:Type DataGridCell}" x:Key="DataGridCellConErrores">
<Setter Property="ToolTipService.ShowOnDisabled" Value="True"/>
<Setter Property="ToolTipService.InitialShowDelay" Value="5000"/>
<Setter Property="ToolTipService.ShowDuration" Value="60000"/>
<Setter Property="ToolTip">
<Setter.Value>
<MultiBinding Converter="{StaticResource ResourceKey=dlgEnviarAlbaranCantidadParaDescontarTooltipMultivalueConverter}">
<MultiBinding.Bindings>
<Binding Path="(ap:CeldasDatagridConErroresAttachedProperty.TextoTooltip01)"/>
<Binding Path="(ap:CeldasDatagridConErroresAttachedProperty.TextoTooltip02)"/>
</MultiBinding.Bindings>
</MultiBinding>
</Setter.Value>
</Setter>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=(ap:CeldasDatagridConErroresAttachedProperty.EsDatoCorrecto)}" Value="false"/>
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="Orange"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
This is how I am trying to use in my column of the datagrid:
<DataGridTextColumn Header="Cantidad Para Descontar" Binding="{Binding CantidadParaDescontar, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, ValidatesOnDataErrors=True}" Width="AUTO" IsReadOnly="false"
ap:CeldasDatagridConErroresAttachedProperty.TextoTooltip01="{Binding Path=DescripcionCantidadParaDescontar}"
ap:CeldasDatagridConErroresAttachedProperty.TextoTooltip02="{Binding Path=MotivoCantidadParaDescontarIncorrecta}"
ap:CeldasDatagridConErroresAttachedProperty.EsDatoCorrecto="{Binding Path=EsCantidadParaDescontarCorrecta}"
CellStyle="{StaticResource DataGridCellConErrores}"/>
I can compile and run, but the text of tooltip is always empty and also it doesn't change the color of the background if the data is not correct.
How should I bind the attached properties?
Thanks.
You should bind to the attached property of the column. Try this:
<Binding Path="Column.(ap:CeldasDatagridConErroresAttachedProperty.TextoTooltip01)"/>
On my DataGridTextColumn I would like to run a DataTrigger but only when Validation.HasError is False
This is what I have at the moment:
<DataGridTextColumn Header="Volts"
Binding="{Binding DcVolts, Converter={StaticResource StringToDecimalConverter}}"
Width="Auto">
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}"
BasedOn="{StaticResource DataGridTextColumnElementErrorStyle}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=Validation.HasError}"
Value="False" />
<Condition Value="False">
<Condition.Binding>
<MultiBinding Converter="{StaticResource EqualityConverter}">
<Binding Path="DcVolts" />
<Binding Path="DcSpecVolts" />
</MultiBinding>
</Condition.Binding>
</Condition>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Background" Value="Orange" />
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.ElementStyle>
The thinking behind is that Validation.HasError has to be False for the MultiDataTrigger to set the BackGround to Orange if the result of the EqualityConverter is False
This is because if Validation.HasError is True then I want the usual Pink background that my DataGridTextColumnElementErrorStyle provides when a rule I have set on the Property fails.
I actually got closer with this:
<DataGridTextColumn Header="Volts"
Binding="{Binding DcVolts, Converter={StaticResource StringToDecimalConverter}}"
Width="Auto">
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource DataGridTextColumnElementErrorStyle}">
<Style.Triggers>
<DataTrigger Value="False">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource EqualityConverter}" >
<Binding Path="DcVolts" />
<Binding Path="DcSpecVolts" />
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Background" Value="Orange" />
</DataTrigger>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Background" Value="Pink" />
</Trigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.ElementStyle>
But the problem was that on Validation.HasError the messages provided (by the rules I have created) in the ToolTip where duplicated.
Any advice is greatly appreciated.
You should add parentheses around the binding path since Validation.HasError is an attached property:
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.HasError)}"
Value="True" />
I am trying to change the foreground (text) color of one of the items in a ListBox based on an index value. For example, if the index was 1, then the item at index 1 would have a different text color than all the other items. The index isn't the list selection index but my own value.
I searched around on Google and found some ideas to use AlternationIndex but I can't get it to work that. The converter is either receiving 0 (zero) or DependencyProperty#Unset for the AlternationIndex binding.
Here is my code:
<ListBox x:Name="videoList" SelectionMode="Single" AlternationCount="{Binding Mode=OneWay, Path=Items.Count}" Grid.Column="1" SelectionChanged="videoList_SelectionChanged">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Mode="OneWay" Converter="{StaticResource EqualityConverter}">
<MultiBinding.Bindings>
<Binding ElementName="videoWindow" Mode="OneWay" Path="VideoIndex" />
<Binding RelativeSource="{RelativeSource AncestorType=ListBoxItem}" Path="(ItemsControl.AlternationIndex)" />
</MultiBinding.Bindings>
</MultiBinding>
</DataTrigger.Binding>
<DataTrigger.Setters>
<Setter Property="Foreground" Value="Blue" />
</DataTrigger.Setters>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
For the RelativeSource I've tried: Self, TemplatedParent and AncestorType=ListBoxItem.
I also tried lots of different combinations with the Path value.
I can't get it to work. Any suggestions?
Solution: With the help from Clemens, turns out it was because the binding for the ListBox AlternationCount was incorrect. Oops!
<ListBox x:Name="videoList"
SelectionMode="Single"
AlternationCount="{Binding RelativeSource={RelativeSource Self}, Mode=OneWay, Path=Items.Count}"
Grid.Column="1"
SelectionChanged="videoList_SelectionChanged">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Mode="OneWay" Converter="{StaticResource EqualityConverter}">
<MultiBinding.Bindings>
<Binding ElementName="videoWindow" Mode="OneWay" Path="VideoIndex" />
<Binding RelativeSource="{RelativeSource Self}" Path="(ItemsControl.AlternationIndex)" />
</MultiBinding.Bindings>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Foreground" Value="Blue" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
It works with RelativeSource Self and a large enough AlternationCount, e.g. int.MaxValue.
<ListBox AlternationCount="2147483647" ...>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource EqualityConverter}">
<MultiBinding.Bindings>
<Binding ElementName="videoWindow"
Path="VideoIndex"/>
<Binding RelativeSource="{RelativeSource Self}"
Path="(ItemsControl.AlternationIndex)"/>
</MultiBinding.Bindings>
</MultiBinding>
</DataTrigger.Binding>
<DataTrigger.Setters>
<Setter Property="Foreground" Value="Blue"/>
</DataTrigger.Setters>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
O.K., taking a hint from my previous post, in short how do I get the trigger to fire on an attached property?
After more trial (and much error), I think I know where the problem is, but not how to fix it. When using drag and drop onto the datagrid, the Trigger responsible for changing the background of the DataGridCell only fires on the first drop or load into an unused cell. Outside of removing the data from the cell, in which case the cell returns to the color of the row, any further use of the cell returns its background to the first cell specific color it had and the trigger no longer fires.
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Blue" />
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource watchNameConverter}" ConverterParameter="1">
<Binding RelativeSource="{RelativeSource Self}" Path="Text"></Binding>
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}, AncestorLevel=1}" Path="." />
<Binding RelativeSource="{RelativeSource Self}" Path="."></Binding>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Background" Value="Purple"/>
<Setter Property="local:Scheduler.IsDirty" Value="True" />
</DataTrigger>
<Trigger Property="local:Scheduler.IsDirty" Value="true">
<Setter Property="Background">
<Setter.Value>
<MultiBinding Converter="{StaticResource colorTextConverter}" >
<MultiBinding.Bindings>
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}, AncestorLevel=1}" Path="." />
</MultiBinding.Bindings>
</MultiBinding>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
The alternate row style is defined as:
<Style TargetType="telerik:GridViewRow">
<Setter Property="Background" Value="{Binding Color,Converter={StaticResource dataToColorConverter}}">
</Style>
But I want to update the rowstyle depedninng on multiple values. I want to achieve something like this.
<Style>
<Setter Property="Background" >
<MultiBinding Converter={StaticResource dataToColorConverter}>
<Binding Path="Color"/>
<Binding ElementName="myListBox" Path="SelectedItem"/>
</MultiBinding>
</Setter>
</Style>
But getting the error "The type 'Setter' does not support direct content."
Because the Setter element doesn't support direct content, you must specify that you are setting the Value property (include "<Setter.Value>" in your XAML):
<Setter Property="Background" >
<Setter.Value>
<MultiBinding Converter="{StaticResource dataToColorConverter}" >
<Binding Path="Color" />
<Binding ElementName="myListBox" Path="SelectedItem" />
</MultiBinding>
</Setter.Value>
</Setter>