Wpf Tooltip and Binding to Label Content - wpf

I have a lot of labels on my wpf App like this.
<Label Style="{StaticResource styleLabelTitle}">
<TextBlock TextTrimming="CharacterEllipsis" Text="{localization:Translate geolocation_controls}">
</TextBlock>
</Label>
I want to add a tooltip to show complete name when ellipsis is working. So i add the tooltip in the label style.
<Style x:Key="styleLabelTitle" TargetType="Label" x:Shared="False">
<Setter Property="Foreground" Value="{StaticResource brushTextsForeground}"></Setter>
<Setter Property="FontWeight" Value="Bold"></Setter>
<Setter Property="FontFamily" Value="Consolas"></Setter>
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content}" />
</Style>
The problem is that I think when tooltip is appearing is changing the textblock parent. So the text is only appearing in the Tooltip and is removed from the original label.
Any ideas?
Thanks in advance.

I finally came to a solution by doing a new style.
<Style x:Key="styleLabelText" TargetType="{x:Type Label}"
x:Shared="False">
<Setter Property="Foreground" Value="{StaticResource brushTextsForeground}"></Setter>
<Setter Property="FontWeight" Value="Normal"></Setter>
<Setter Property="FontFamily" Value="Consolas"></Setter>
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Label}">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" TextTrimming="CharacterEllipsis"
Text="{TemplateBinding Content}" />
</ControlTemplate>
</Setter.Value>
</Setter> </Style>

You only have an instance of the textblock, then when you assign it to the tooltip the content is lost as you said.
You should set the value of the tooltip with the translated text out of the style:
<Label Style="{StaticResource styleLabelTitle}" ToolTip="{localization:Translate geolocation_controls}">
<TextBlock ...>
</Label>

Related

Unable to set Tool Tip content in style

I tried to set the Tooltip content property in style. But Tooltip text is displayed as System.Windows.Style. Can someone help me with what I am doing wrong?
<TextBlock HorizontalAlignment="Left" Margin="149,45,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Height="29" Width="121">
<TextBlock.ToolTip>
<Style TargetType="{x:Type ToolTip}">
<Setter Property="Content" Value="ToolTip Test"/>
<Setter Property="Foreground" Value="Red"/>
<Setter Property="Foreground" Value="White"/>
</Style>
</TextBlock.ToolTip>
</TextBlock>
You have to assign a ToolTip to the TextBox.ToolTip property and then assign the Style to ToolTip.Style:
<TextBlock HorizontalAlignment="Left" Text="TextBlock">
<TextBlock.ToolTip>
<ToolTip>
<ToolTip.Style>
<Style TargetType="{x:Type ToolTip}">
<Setter Property="Content" Value="ToolTip Test" />
<Setter Property="Foreground" Value="Red" />
<Setter Property="Foreground" Value="White" />
</Style>
</ToolTip.Style>
</ToolTip>
</TextBlock.ToolTip>
</TextBlock>
When setting FrameworkElement.ToolTip directly, the object is wrapped implicitly into a ToolTip. Since Style isn't a FrameworkElement and cannot be rendered, the ContentControl (ToolTip) invokes object.ToString on the content (the Style in your case) which returns the fully qualified type name as string by default.

WPF Binding children property of a custom control to parent

I'm new to WPF. I'm trying to create a custom control with a HorizontalContentAlignment property that will change according to the setting of the container.
<Style x:Key="SimpleRadioButton" TargetType="{x:Type RadioButton}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Margin" Value="20 10 20 0"/>
<Setter Property="Height" Value="24"/>
<Setter Property="Padding" Value="6"/>
<Setter Property="HorizontalContentAlignment" Value="{Binding RelativeSource={RelativeSource TemplatedParent}}"/>
</Style>
And then set them in the parent container.
<ctrl:ToggleExpander
Header="Worklist"
IsChecked="{Binding IsVisible, Mode=TwoWay}"
HorizontalContentAlignment="Right"
IsToggleEnabled="True">
<StackPanel>
<ctrl:SideBarPanel
HorizontalContentAlignment="Right"
Header="map provider">
<RadioButton
Content="Finished"
IsChecked="True"
Style="{DynamicResource SimpleRadioButton}"/>
</StackPanel>
</ctrl:ToggleExpander>
But it doesn't seem to work. Is there any way to go about it? Thanks! And sorry for my English.
you could use the following, and your radiobutton will take the value of the first parent framework element (for example in this case your ctrl:SideBarPanel)
<Setter Property="HorizontalContentAlignment" Value="{Binding RelativeSource={RelativeSource AncestorLevel=1, AncestorType=FrameworkElement}, Path=HorizontalContentAlignment}"/>
you could use this symply way in xaml:
<Setter Property="HorizontalAlignment">
<Setter.Value>
<Binding Path="HorizontalAlignment" RelativeSource="{RelativeSource AncestorLevel=1,AncestorType=FrameworkElement}" />
</Setter.Value>
</Setter>
I hope help you

WPF Style Binding to Base Style

i have a base style and a style in wpf.
the base style is:
<Style x:Key="BaseTextBox" TargetType="{x:Type TextBox}">
<Setter Property="Background" Value="#DDFFDD" />
<Setter Property="MinWidth" Value="75" />
<Setter Property="behaviors:OCCInteraction.Triggers" Value="{StaticResource ResourceKey=validationTrigger}" />
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="Background" Value="#FFDDDD"/>
<Setter Property="ToolTip" Value="{Binding Path=(Validation.Errors)[0].ErrorContent, RelativeSource={x:Static RelativeSource.Self}}" />
</Trigger>
</Style.Triggers>
</Style>
And the the specific style is:
<Style x:Key="EditableTextBox" TargetType="{x:Type TextBox}" BasedOn="{StaticResource ResourceKey=BaseTextBox}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<StackPanel Orientation="Horizontal">
<Border BorderBrush="Red" BorderThickness="1" Padding="0" Margin="0">
<AdornedElementPlaceholder Margin="0"/>
</Border>
<TextBlock Text="test" />
<Image Style="{StaticResource ResourceKey=WarningImage}"/>
<TextBlock Text="{Binding Path=(Validation.Errors)[0].ErrorContent, RelativeSource={RelativeSource Mode=Self,AncestorLevel=2}}" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Now i want to add the Validation Error Text to a textblock next to the image. But the Same Binding Path doesn't work. I've tried diferent bindings, but I can't figure out how to access the same binding like on the base style.
Thanks for help :)
Have you tried it without the AncestorLevel? You should be the same object.
You cannot use Mode=Self and AncestorLevel properties. Just use Mode=Self.
Ancestor level is used when you try to reach parent of that control in visual tree.

How to get rid of the red border when a DataGrid cell is invalid?

How do I do this? I want to get rid of that annoying red border that shows on each invalid datagrid cell.
You can just add this line to your DataGrid:
<DataGrid Validation.ErrorTemplate="{x:Null}" />
I had this same issue but in my case I wasn't using IDataError or INotifyDataErrorInfo. I'm using a custom ValidationRule and styles to handle my validation logic and presentation. I was already using the DataGrid RowStyle to display a custom style for the row that has errors so I thought it would be easy to do something similar with the DataGridCell.
Things to note:
You can't just define a style and set the DataGrid.CellStyle. Instead you have to use the ElementStyle and/or the EditingElementStyle.
The style TargetType has to match the DataGridColumn type that the cell is using. So for a DataGridComboBoxColumn the TargetType should be ComboBox
DataGrid Column XAML:
<DataGridComboBoxColumn Header="Column1"
ItemsSource="{Binding Path=Column1Path}"
DisplayMemberPath="Column1DisplayPath"
ElementStyle="{StaticResource DGComboColValidationStyle}"
EditingElementStyle="{StaticResource DGComboColValidationStyle}">
<DataGridComboBoxColumn.SelectedItemBinding>
<Binding Path="Column1Path" UpdateSourceTrigger="LostFocus">
<Binding.ValidationRules>
<Validation:CustomValidationRule ValidationStep="UpdatedValue" ValidatesOnTargetUpdated="True" />
</Binding.ValidationRules>
</Binding>
</DataGridComboBoxColumn.SelectedItemBinding>
</DataGridComboBoxColumn>
Style Definitions
<Style x:Key="DGComboColValidationStyle" TargetType="{x:Type ComboBox}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<Grid>
<Border BorderThickness="1"
BorderBrush="{Binding ElementName=adorner1, Path=DataContext[0].ErrorContent.ValidationType, Converter={StaticResource ValidationTypeColorConverter}}"
CornerRadius="3">
</Border>
<AdornedElementPlaceholder Name="adorner1"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="DGTextColValidationStyle" TargetType="{x:Type TextBlock}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<Grid>
<Border BorderThickness="1"
BorderBrush="{Binding ElementName=adorner2, Path=DataContext[0].ErrorContent.ValidationType, Converter={StaticResource ValidationTypeColorConverter}}"
CornerRadius="3">
</Border>
<AdornedElementPlaceholder Name="adorner2"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="DGRowValidationStyle" TargetType="{x:Type DataGridRow}">
<Setter Property="ValidationErrorTemplate">
<Setter.Value>
<ControlTemplate x:Name="DGRowValidationTemplate">
<Grid>
<Ellipse Width="12" Height="12" Stroke="Black" StrokeThickness="0.5"
Fill="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridRow}}, Path=(Validation.Errors)[0].ErrorContent.ValidationType, Converter={StaticResource ValidationTypeColorConverter}}"/>
<TextBlock FontWeight="Bold" Padding="4,0,0,0"
Margin="0" VerticalAlignment="Top" Foreground="White" Text="!"
ToolTip="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridRow}}, Path=(Validation.Errors)[0].ErrorContent.ValidationMessage}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="BorderBrush" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent.ValidationType, Converter={StaticResource ValidationTypeColorConverter}}"/>
</Trigger>
<Trigger Property="Validation.HasError" Value="false">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent" />
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="DGCellStyle" TargetType="{x:Type DataGridCell}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="false">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridRow}}, Path=(Validation.Errors)[0].ErrorContent.ValidationMessage}"/>
</Trigger>
</Style.Triggers>
</Style>
Reference:
http://social.msdn.microsoft.com/Forums/vstudio/en-US/6d2d6513-7bca-4359-a12b-46da3c380b0a/wpf-4-datagrid-editingelementstyle-and-validationerrortemplate-adorner-layer?forum=wpf
Set the ValidatesOnDataErrors and ValidatesOnExpcetions to False for your binding of your cell.
In case you want your validations, then you have to override the Validation Template for your control. Please refer to my answer here -
Validation Error Style in WPF, similar to Silverlight
I hated the red border because it was put in the adorner and adorners sit on top of the window, meaning that if your element is partially/fully hidden by another element (like it is in a grid) the full adorner still shows :(
That didn't mean I didn't want some customization though, so I can still highlight my items in pink, or change their foreground and have the DataGridCell correctly clip everything off. You can do this by using a style trigger.
Hope this helps!
<DataGrid.Resources>
<Style TargetType="{x:Type TextBlock}" x:Key="TextBlockErrorStyle">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<!-- Just the adorned element means NO RED BORDER -->
<AdornedElementPlaceholder Name="controlWithError" />
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="Background" Value="Pink"/>
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
...
<DataGridTemplateColumn Header="Description" MinWidth="150">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Description, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, NotifyOnValidationError=True}"
Style="{StaticResource ResourceKey=TextBlockErrorStyle}"
/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
You can check this as well
How to: Implement Validation with the DataGrid Control

Bind datatrigger style to a property of the content binding objet

I'm trying to do the following. I have a label bound to an object that have two properties. One I want to display and one I want to use for the datatrigger.
Here what's I've come up with yet :
<Label Grid.Row="5" Content="{Binding ElementName=InformationUserControl, Path=Info.ObjectBound}">
<Label.Style>
<Style TargetType="{x:Type Label}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource self}, Path=Content.InterpretationValue}">
<DataTrigger.Value>
<enums:DataInterpretation>Neutral</enums:DataInterpretation>
</DataTrigger.Value>
<Setter Property="Background" Value="Red" />
</DataTrigger>
</Style.Triggers>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Label}">
<TextBlock Text="{TemplateBinding Content.Value}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Label.Style>
</Label>
The problem is that my Template overrides the default one so it display nothing. Is there a way to make it work?
Thanks !
I think the problem is not that you override the template but that the binding is broken, i would try this:
<TextBlock Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Content.Value}" />

Resources