How to put tooltips depending on togglebutton's state, WPF - c#

I created a toggle button in WPF. Each state is represented by an image.
It looks like that:
<ToggleButton Click="ButtonEnable_Click" x:Name="ButtonEnable" Width="36" Height="36" ToolTipService.ShowOnDisabled="true" >
<ToggleButton.Resources>
<BitmapImage x:Key="imgNormal" UriSource="/Project;component/Resources/images/Image-active.png"/>
<BitmapImage x:Key="imgChecked" UriSource="/Project;component/Resources/images/Image-inactive.png"/>
</ToggleButton.Resources>
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Image x:Name="PART_Image" Source="{StaticResource imgNormal}"/>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter TargetName="PART_Image" Property="Source" Value="{StaticResource imgChecked}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="PART_Image" Property="Source" Value="{StaticResource imgNormal}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ToggleButton.Style>
</ToggleButton>
And everything works fine.
But i want to create a tooltip for each state of my togglebutton.
One "Active, blabla".
And the other "Inactive blabla".
And my software has to be localized, so the text of the tooltip is based on a ressource (en, fr, de, etc).
From what i saw, i am pretty sure it's a simple keyword or something... But i don't know what keyword, and where i have to put it...
Thanks a lot.
Bye.

You can simply set the Tooltip property
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="ToolTip" Value="Active"></Setter>
</Trigger>
</Style.Triggers>
<Setter Property="ToolTip" Value=""></Setter>
</Style>
</ToggleButton.Style>

Use Style something like:
<Trigger Property="IsChecked" Value="True">
<Setter Property="ToolTip" Value="{x:Static local:MainWindow.Tooltip1}"/>
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="ToolTip" Value="{x:Static local:MainWindow.Tooltip2}"/>
</Trigger>
Property: Use CLR property to get values from Resource file
private static string tooltip1;
public static string Tooltip1
{
get
{
if (tooltip1 == null)
{
tooltip1 = "";//get this value form Resources
}
return tooltip1;
}
}

Related

C# WPF RibbonButton Change Icon on MouseOver

i have a Ribbonbutton wich i want to change the Icon on MouseOver but it does not seem to work.
Here is my Code:
<RibbonButton Label="Verbindung testen" LargeImageSource="../Resources/Buttons/disconnect.png" Command="{Binding SettingsVM.TestConnectionCommand}">
<RibbonButton.Style>
<Style TargetType="{x:Type RibbonButton}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="LargeImageSource" Value="../Resources/Buttons/connect.png"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="LargeImageSource" Value="../Resources/Buttons/disconnect.png"/>
</Trigger>
</Style.Triggers>
</Style>
</RibbonButton.Style>
</RibbonButton>
It just shows the first Icon "disconnect.png" and on mouse over it gets highlighted like all the other buttons, but no image change.
I also tried it this way, with ControlTemplate:
<RibbonButton Label="Verbindung testen" LargeImageSource="../Resources/Buttons/disconnect.png" Command="{Binding SettingsVM.TestConnectionCommand}">
<RibbonButton.Template>
<ControlTemplate TargetType="{x:Type RibbonButton}">
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="LargeImageSource" Value="../Resources/Buttons/connect.png"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="LargeImageSource" Value="../Resources/Buttons/disconnect.png"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</RibbonButton.Template>
Here it doesnt show an icon at all.
Found the Answer!
WPF RibbonButton: LargeImageSource and Label not updated via DataTriggers
The problem is your setting properties for LargeImageSource and Label in the button itself. When you do this it takes precidence over your style triggers. I suggest using setters in the style to set your defaults, and remove the property settings it the button.
So it has to be:
<RibbonButton Label="Verbindung testen" Command="{Binding SettingsVM.TestConnectionCommand}">
<RibbonButton.Style>
<Style TargetType="{x:Type RibbonButton}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="LargeImageSource" Value="../Resources/Buttons/connect.png"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="LargeImageSource" Value="../Resources/Buttons/disconnect.png"/>
</Trigger>
</Style.Triggers>
</Style>
</RibbonButton.Style>
Removing the "LargeImageSource" from the Button itself.

Multiple styles and content on one button

I have a HomePage with a number of buttons on that I am trying to get to do a couple of things. Firstly, I have a Style in a ResourceDictionary that dictates the overall 'look and feel' of the buttons. It looks like this:
<Style TargetType="Button" x:Key="HomeButton">
<Setter Property="Foreground" Value="White"/>
<Setter Property="Background" Value="#06658D"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}" BorderBrush="White" BorderThickness="1">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Background" Value="White"/>
<Setter Property="Foreground" Value="#06658D"/>
</Trigger>
</Style.Triggers>
</Style>
Nothing too complicated, however I want the MouseOver effect to persist after being clicked. So now I am looking at doing something like this:
<Button Grid.Row="0" Style="{StaticResource HomeButton}" Content="Contacts">
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<DataTrigger Binding="{Binding ContactsClicked}" Value="True">
<Setter Property="Background" Value="White"/>
<Setter Property="Foreground" Value="#06658D"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button>
I'll bind the command element of the Button to set ContactsClicked = true and reset this when another button is pressed. However, I get the error saying that Content is set multiple times.
Is it possible to have an overall Style of the Button set, as well as a 'Clickedstyle and to have aTextBlockdisplaying text on the button all at once or am I approaching this wrong? I am trying to not have an individual overall style for every singleButton`as that's a lot of repeated code.
For clarity this is what I am aiming for:
I've managed to find a solution myself, instead of using a Button us a ToggleButton instead:
<Style TargetType="ToggleButton" x:Key="HomeButton">
<Setter Property="Foreground" Value="White"/>
<Setter Property="Background" Value="#06658D"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Background="{TemplateBinding Background}" BorderBrush="White" BorderThickness="1">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="Black" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Background" Value="White"/>
<Setter Property="Foreground" Value="#06658D"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Background" Value="White"/>
<Setter Property="Foreground" Value="#06658D"/>
</Trigger>
</Style.Triggers>
</Style>
I would add this as a comment but im not allowed.
If your goal is that the button will stay selected after it is clicked, why not use a RadioButton? A RadioButton has a built-in property called IsChecked but will also remain "Checked" or "Selected" even after multiple clicks.
Of course you can define the behavior and the styles in a similar manner, create a simple Trigger on the property IsChecked.
If more explanation is needed, just say so.

How to override a datagrid style

I have a styled window and I want to override a datagrid style to ALL datagrids in my application
<Window.Resources>
<Style x:Name="dtgStyle" TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Transparent" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Blue" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter Property="Background" Value="Transparent" />
</Trigger>
</Style.Triggers>
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="White" />
</Style>
</Window.Resources>
I thougth this had to work but I have to apply
Style s = Resources["dtgStyle"] as Style;
mydtg.Style = s;
now I wouldn't like to have to apply that to ALL dtgs.
The best would be to automatically apply it in xaml.
Thanx
---ADD for ASh----
Thank you for your help. The only problem is that when the datagrid loses focus the selected line in the datagrid changes colour as you can see in the following pic (foreground turns to black).
I have tried to add various property but nothing works.
additionally the left border gets bolder (no pun intended) and larger.
Any idea how to fix it?
Thanks
if you need default style for FrameworkElement, declare it without x:Key, only with TargetType.
Both DataGridRow and DataGridCell have IsSelected property. Not enough to change Background only for DataGridRow, it has to be done for DataGridCell as well
<Style TargetType="{x:Type DataGrid}">
<Setter Property="RowStyle" >
<Setter.Value>
<Style TargetType="{x:Type DataGridRow}" BasedOn="{StaticResource {x:Type DataGridRow}}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="White" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Transparent" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Orange" />
<Setter Property="Foreground" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</Setter.Value>
</Setter>
<Setter Property="CellStyle">
<Setter.Value>
<Style TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource {x:Type DataGridCell}}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Orange" />
</Trigger>
<DataTrigger Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" Value="False">
<Setter Property="Foreground" Value="White"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Setter.Value>
</Setter>
</Style>
fix for Foreground was found here: DataGrid's selected row color when inactive (https://stackoverflow.com/a/25204493/1506454)

Visual studio extension resource files

I have developed a visual studio extension and I have a custom button that I want to style using PNG images, but the image files/resource files wont show while in action and the button is blank.
I have a custom button template.
<Style x:Key="openFilebtn" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Name="bgGrid">
<Image Name="btn_bg" Source="/vsPlayer;component/Resources/open.png"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsDefaulted" Value="True">
<Setter Property="Source" TargetName="btn_bg" Value="/vsPlayer;component/Resources/open.png"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Source" TargetName="btn_bg" Value="/vsPlayer;component/Resources/open_hover.png"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Source" TargetName="btn_bg" Value="/vsPlayer;component/Resources/open.png"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Source" TargetName="btn_bg" Value="/vsPlayer;component/Resources/open.png"/>
<Setter Property="Opacity" TargetName="btn_bg" Value="0.5"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
So like I was saying, always make sure you have your build action property set correctly on assets like images you're including in the build. In your case, setting it to Resource does the trick.
Glad you got your remedy, cheers!

How to display validation error in button bound to command

I am developing an app and trying to stick to an MVVM model, I have a button that is just bound to a command. Currently the command can be enabled / disabled and greys out the button when the command is set to CanExecute false. But I want to add the ability to show validation errors on the button (by changing its color to red, maybe showing a tooltip).
The validation is currently already shown in another location in the UI, but the users are getting annoyed that the button is enabled and they click it only to have a message box pops up telling them they shouldn't of clicked the button because there is a validation error. But just disabling the button completely without showing them why would make the users confused(since they overlook the large red validation error at the bottom of the screen). So how can I show additional information on the save button?
This is my current button xaml:
<Button Name="SaveDataPointButton" Style="{StaticResource ImageButton}" Command="{Binding OpenDataPoint.SaveDataPointEditsCommand}" Margin="5,0" VerticalAlignment="Stretch">
<Image Source="save.png" Stretch="None" ToolTip="Save Edits"/>
</Button>
And the style that is changing its appearance when IsEnabled is false, is it possible to somehow inspect some other command state from the style to make the button red during validation errors?
<!-- Style for all of the nav and save buttons in the datapoints view -->
<Style x:Key="ImageButton" TargetType="Button">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border
x:Name="Border"
BorderThickness="0">
<ContentPresenter
Margin="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RecognizesAccessKey="True"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="Border" Property="Background">
<Setter.Value>
<SolidColorBrush Color="LightGray"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter TargetName="Border" Property="Background">
<Setter.Value>
<SolidColorBrush Color="Gray"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" Value="0.3"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Command" Value="{x:Null}">
<Setter Property="IsEnabled" Value="False"/>
</Trigger>
</Style.Triggers>
</Style>
I ended up using a DataTrigger bound to another property on the view model to change the background color, but because I was setting a ControlTemplate in the style, the only way I could figure out to make the DataTrigger apply a background change was to copy the entire style and put the DataTrigger on the Border element in the control template. Since apparently you can't reference a child element from the new ControlTemplate from outside that control template.
<!-- Style for all of the nav and save buttons in the datapoints view -->
<Style x:Key="ImageSaveButton" TargetType="Button">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border
x:Name="Border"
BorderThickness="0">
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<DataTrigger Binding="{Binding OpenDataPoint.HasValidationError}" Value="True">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<ContentPresenter
Margin="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RecognizesAccessKey="True"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="Border" Property="Background">
<Setter.Value>
<SolidColorBrush Color="LightGray"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter TargetName="Border" Property="Background">
<Setter.Value>
<SolidColorBrush Color="Gray"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" Value="0.3"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Command" Value="{x:Null}">
<Setter Property="IsEnabled" Value="False"/>
</Trigger>
</Style.Triggers>
</Style>

Categories