How to make ToolTips have rounded corners - WPF - c#

I've created a small WPF application and have a number of TextBoxes on the page. All of these TextBoxes have rounded corners.
I have used the MVVM pattern and implemented the IDataErrorInfo interface to display errors to the user. When one of the TextBoxes is empty the edges, ToolTips should be displayed Red which I have successfully done.
I now want the red edge to also have rounded corners like the TextBoxes. As shown in the image the red border is shown as the TextBox is empty, The red border needs to have a corner radius.
<!-- Text box xaml code that is used to display the error and binding -->
<TextBox Style="{StaticResource TextBoxBase}"
Name="FirstName"
Text="{Binding FirstName, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, Source={StaticResource CustomerObject}, ValidatesOnDataErrors=True}"/>
<!-- Code that changes the tool tip if it's null -->
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors).CurrentItem.ErrorContent}" />
</Trigger>
</Style.Triggers>

You could create a specific Tooltip Style for errors:
Here an example of a custom Tooltip style with CornerRadius = "4":
<Style x:Key="ErrorRoundedTooltip" TargetType="ToolTip">
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="HasDropShadow" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border Name="Border" CornerRadius="4"
BorderThickness="1"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}">
<ContentPresenter Margin="4" HorizontalAlignment="Left" VerticalAlignment="Top" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Content">
<Setter.Value>
<ItemsControl ItemsSource="{Binding Path=(Validation.Errors)}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ErrorContent.ValidationMessage}" VerticalAlignment="Center"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Setter.Value>
</Setter>
</Style>
<ToolTip x:Key="ErrorRepository" Style="{StaticResource ErrorRoundedTooltip}" />
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip" Value="{StaticResource ErrorRepository}" />
</Trigger>
</Style.Triggers>
</Style>

Related

How can I add something to my custom listbox?

I made a custom listbox but when I push the button show every language nothing is showing. How can I fix this. When I delete the listbox style it just works fine. It's all in C#.
I hope you can help me.
greetings
Elias
<ListBox x:Name="lsbResultaatTaal"
Foreground="Black"
FontSize="15"
Grid.Row="1"
Margin="528,56,0,0"
Height="450"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Width="233">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{d:SampleData ItemCount=5}"/>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.Style>
<Style TargetType="ListBox">
<Setter Property="Background" Value="Gray"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Gray"/>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.Style>
<ListBox.Template>
<ControlTemplate TargetType="ListBox">
<Border Width="230" Height="450"
CornerRadius="9"
BorderThickness="1"
BorderBrush="Black"
Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</Border>
</ControlTemplate>
</ListBox.Template>
</ListBox>
You can set style in resources
<Window.Resources>
<Style TargetType="{x:Type ListBox}">
<Setter Property="Background" Value="Gray" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Gray" />
<!--
Why you choose same background color when hover listbox
Maybe same color your background and foreground
-->
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
OR
Can you try below changes:
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
<ContentPresenter
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{Binding YourProp}" />

Using style triggers on a static resource style to change more than properties

I am using Material Design XAML and I am trying to set a togglebutton icon and background color to something else when checked.
RED BOX CODE
<ToggleButton ToolTip="MaterialDesignFlatPrimaryToggleButton"
IsChecked="False"
Grid.Column="2"
Margin="78,58,99,52"
Grid.Row="1">
<Style TargetType="ToggleButton"
BasedOn="{StaticResource MaterialDesignFlatPrimaryToggleButton}">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="Green" />
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton>
GREEN BOX CODE
<ToggleButton Style="{StaticResource MaterialDesignFlatPrimaryToggleButton}"
ToolTip="MaterialDesignFlatPrimaryToggleButton"
IsChecked="False"
Grid.ColumnSpan="2"
Grid.Column="3"
Margin="205,58,188,52"
Grid.Row="1">
<md:PackIcon Kind="WindowClose"
Foreground="Red"
Height="21"
Width="21"/>
</ToggleButton>
I was thinking I could use the basedon attribute to reserve the style with material design...if possible.
I am trying reserve the style and change the icon and set background color when checked to look like this:
How would I do this?
You are currently setting the Style as the ToggleButton.Content.
You've got to define the Style nested into the ToggleButton.Style property:
<ToggleButton ToolTip="MaterialDesignFlatPrimaryToggleButton"
IsChecked="False"
Grid.Column="2"
Margin="78,58,99,52"
Grid.Row="1">
<ToggleButton.Style>
<Style TargetType="ToggleButton"
BasedOn="{StaticResource MaterialDesignFlatPrimaryToggleButton}">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="Green" />
<Setter Property="Content">
<Setter.Value>
<md:PackIcon Kind="SmileyHappy" />
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>

Styling a WPF Passwordbox

I'm currently trying to do the following:
If no password is entered a text "Password" should be shown.
But with my template no password is shown, and if i'm using a decorator or a scrollviewer i can't change the color of the text.
Do you have any ideas to achieve this?
Here's my styling code:
<Style TargetType="{x:Type PasswordBox}" x:Key="Password">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="PasswordBox">
<Grid>
<PasswordBox Background="{StaticResource BrushDark}" Foreground="{StaticResource BrushTextNormal}" BorderBrush="{StaticResource BrushBorderInput}" BorderThickness="1"/>
<TextBlock HorizontalAlignment="Left"
VerticalAlignment="Center"
Text="Password"
Margin="5,0,5,0"
Foreground="#ff808080"
IsHitTestVisible="False"
x:Name="UserMessage"
Visibility="Hidden"/>
<!--<ScrollViewer Foreground="{StaticResource BrushTextNormal}" Background="{StaticResource BrushTextNormal}" x:Name="PART_ContentHost"/>-->
<!--<Decorator TextBlock.Foreground="White" x:Name="PART_ContentHost"/>-->
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Tag" Value=""/>
<Condition Property="IsKeyboardFocusWithin" Value="False"/>
</MultiTrigger.Conditions>
<Setter Property="Visibility" TargetName="UserMessage" Value="Visible"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
If you create custom ControlTemplate for PasswordBox or TextBox you need to put ScrollViewer named x:Name="PART_ContentHost instead of inner PasswordBox
From PasswordBox Syles and Templates
PART_ContentHost - A visual element that can contain a FrameworkElement. The text of the PasswordBox is displayed in this element.
And change Foreground as another Setter in you Style. Also, as a side node, I would do the same with Background and use TemplateBinding in your ControlTemplate. This will give more flexibility and allow you to change Background and/or Foreground manually without changing ControlTemplate
<Style TargetType="{x:Type PasswordBox}" x:Key="Password">
<Setter Property="Foreground" Value="{StaticResource BrushTextNormal}" />
<Setter Property="Background" Value="{StaticResource BrushDark}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type PasswordBox}">
<Grid Background="{TemplateBinding Background}">
<ScrollViewer x:Name="PART_ContentHost" .../>
<TextBlock .../>
</Grid>
<ControlTemplate.Triggers>
<!-- removed -->
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

ToggleButton style not working when in treeview

I have a treeview with buckets and parts. Everything looks great except one feature. A property on bucket (bool IsEditable) allows the user to toggle editing on or off within the tree view for that node. But for some reason when wpf displays the collection of buckets in the treeview the togglebuttons do not show the proper text
Here is my xaml:
<Style TargetType="{x:Type ToggleButton}" x:Key="Editor">
<Style.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Content">
<Setter.Value>
<TextBlock Text="Edit"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content">
<Setter.Value>
<TextBlock Text="Done"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
<DataTemplate x:Key="HierarchialItemTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding BucketQty, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text=" "/>
<TextBlock Text="{Binding PartNum}"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="DisplayBucket">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Sequence}"/>
<TextBlock Text=" "/>
<TextBlock Text="{Binding Description}"/>
<ToggleButton IsChecked="{Binding IsEditable}" Width="25" Style="{StaticResource Editor}"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="EditBucket">
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding Sequence}"/>
<TextBlock Text=" "/>
<TextBox Text="{Binding Description}"/>
<ToggleButton IsChecked="{Binding IsEditable}" Width="25" Style="{StaticResource Editor}"/>
</StackPanel>
</DataTemplate>
<HierarchicalDataTemplate x:Key="TreeTemplate"
DataType="{x:Type domain:Bucket}"
ItemsSource="{Binding Parts}"
ItemTemplate="{StaticResource HierarchialItemTemplate}"
>
<ContentPresenter Content="{Binding}"
Style="{DynamicResource TreeNodeStyle}"/>
</HierarchicalDataTemplate>
<Style TargetType="{x:Type ContentPresenter}" x:Key="TreeNodeStyle">
<Setter Property="ContentTemplate" Value="{StaticResource DisplayBucket}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsEditable}" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource EditBucket}"/>
</DataTrigger>
</Style.Triggers>
</Style>
The above is window.resources. In the Grid is
<TreeView x:Name="Buckets"
ItemsSource="{Binding Model.Job.Buckets}"
ItemTemplate="{StaticResource TreeTemplate}"
>
So for whatever reason when I add nodes I get a bucket with a toggle button, but the toggle button text only shows up for the last node added. If I click a toggle button, the text disappears out of the previous toggle button and shows up in the one just clicked. The effect is similar to what this person experienced, but I have no idea what the guy was talking about who answered the question ToggleButton Style only works on last ToggleButton.
Any thoughts?
You have couple of options (ordered from least to most dramatic):
1) Content
<Style TargetType="{x:Type ToggleButton}" x:Key="Editor">
<Style.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Content" Value="Edit" />
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content" Value="Done" />
</Trigger>
</Style.Triggers>
</Style>
2) ContentTemplate
<Style TargetType="{x:Type ToggleButton}" x:Key="Editor">
<Style.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="Edit"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="Done"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
3) ControlTemplate
<Style TargetType="{x:Type ToggleButton}" x:Key="Editor">
<Style.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<TextBlock Text="Edit"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<TextBlock Text="Done"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
The reason why your approach didn't work is that TextBlock control is created only once (i.e. not created as part of template - ControlTemplate or DataTemplate).

How to make value of a custom control editable upon receiving focus

I created a custom WPF control which displays the value of the Weight property which is an int. When the user clicks on the custom control or when the control gets the focus, the user should be able to edit the value of the Weight property.
To accomplish this, I tried the following:
If the control is "inactive", the Weight property will be displayed
in a TextBlock.
If the control gets the focus, the Weight property
will be displayed in a TextBox.
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfCustomControlLibrary1">
<Style TargetType="{x:Type local:CustomControl1}">
<Style.Resources>
<ControlTemplate x:Key="Control_Focused" >
<Border Background="Green"
BorderBrush="Black"
CornerRadius="50" Width="40" Height="40">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBox Width="35"
Text="{Binding Mode=TwoWay,Path=Model.Weight,UpdateSourceTrigger=PropertyChanged,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type local:CustomControl1}}
,Converter={x:Static local:CustomControl1.IntToStringConverter}}" />
</StackPanel>
</Border>
</ControlTemplate>
<ControlTemplate x:Key="Control">
<Border Background="Green"
BorderBrush="Black"
CornerRadius="50" Width="40" Height="40">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock x:Name="PART_TextBlockWeighted" Text="{Binding Mode=TwoWay,Path=Model.Weight,UpdateSourceTrigger=PropertyChanged,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type local:CustomControl1}}}"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</StackPanel>
</Border>
</ControlTemplate>
</Style.Resources>
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Template" Value="{StaticResource Control_Focused}" ></Setter>
</Trigger>
<Trigger Property="IsFocused" Value="False">
<Setter Property="Template" Value="{StaticResource Control}" ></Setter>
</Trigger>
</Style.Triggers>
</Style>
The problem with this custom control style is that when the user clicks into the TextBox, the trigger will change the control template to the TextBlock. How can I fix this?
Try using the IsKeyboardFocusWithin property instead. I believe this will do what you need.
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="Template" Value="{StaticResource Control_Focused}" ></Setter>
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="False">
<Setter Property="Template" Value="{StaticResource Control}" ></Setter>
</Trigger>
</Style.Triggers>

Categories