Beginner : problem with global style in xaml - wpf

In first, sorry for my english ^^
I'm doing an application in wpf, with c# language.
I try to apply a button style for all my buttons, labels and textboxs, to have the property TextWrapping="Wrap" every where. I do this Resource :
<Application.Resources>
<Style TargetType="TextBox">
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
<Style TargetType="Label">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{TemplateBinding Content}" TextWrapping="Wrap"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="Button">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{TemplateBinding Content}" TextWrapping="Wrap"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
It does what I want :
My buttons render.
But now, I would like to put an image, but this style imposes itself and I don't know how to cancel this style.
I tried :
<Window.Resources>
<Image x:Key="icon_exit" Source="src/icon_exit.png"/>
<Image x:Key="icon_info" Source="src/icon_info.png"/>
<Image x:Key="icon_fullscreen" Source="src/icon_fullscreen.png"/>
</Window.Resources>
and
<Button Click="RobotInfoPage" Content="{StaticResource icon_info}" Grid.Column="10" Padding="10"/>
<Button Click="ToogleFullscreen"Content="{StaticResource icon_fullscreen}"Grid.Column="11" Padding="10"/>
<Button Click="Exit" Content="{StaticResource icon_exit}" Background="Red" Grid.Column="12" Padding="10"/>
But it is not the solution :
My buttons render with picture -> Empty buttons
If someone could me explain who do that, it will be super ! :)
Thank's to you.

Related

WPF DataGridTemplateColumn background color not changing on datagrid row selected

I have below WPF Toolkit DataGrid. I have created a custom column using DataGridTemplateColumn which contains a toggle button (without text).
When datagrid row is selected, toggle button background color is correctly changed with the same color as row selection but the cell's background is not changing the color, it remains white. Why?
This is the appearance of the DataGridTemplateColumn column before and after row selection.
Before:
After:
Here the code:
<UserControl.Resources>
<ResourceDictionary>
<!-- Body content datagrid cell vertical centering -->
<Style x:Key="Body_Content_DataGrid_Centering" TargetType="{x:Type dg:DataGridCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type dg:DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</UserControl.Resources>
<!-- Other Stuff -->
<dg:DataGrid x:Name="MyDg"
ItemsSource="{Binding Path=ListOfItems}"
Margin="3 5 5 5"
AutoGenerateColumns="False"
CanUserAddRows="False" CanUserResizeRows="False"
SelectionMode="Single"
SelectedItem="{Binding Path=MySelectedItem}"
ColumnWidth="*"
AlternationCount="2"
Focusable="False" SelectionUnit="FullRow"
CellStyle="{StaticResource Body_Content_DataGrid_Centering}">
<dg:DataGrid.Columns>
<dg:DataGridTemplateColumn Header="Selection" Width="Auto" CanUserResize="False">
<dg:DataGridTemplateColumn.CellStyle>
<Style TargetType="dg:DataGridCell">
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
</dg:DataGridTemplateColumn.CellStyle>
<dg:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ToggleButton Content="" IsChecked="{Binding Path=IsSelected}">
<ToggleButton.Template>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<StackPanel Orientation="Horizontal">
<Image MaxWidth="32" MaxHeight="32">
<Image.Style>
<Style>
<Setter Property="Image.Source" Value="/My.Graphics;component/PNG/Unchecked.png" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type ToggleButton}}}" Value="True">
<Setter Property="Image.Source" Value="/My.Graphics;component/PNG/Checked.png" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<!-- <ContentPresenter Content="{TemplateBinding Content}" Margin="0,0,0,0" />-->
</StackPanel>
</ControlTemplate>
</ToggleButton.Template>
</ToggleButton>
</DataTemplate>
</dg:DataGridTemplateColumn.CellTemplate>
</dg:DataGridTemplateColumn>
</dg:DataGrid.Columns>
</dg:DataGrid>
Finally, I have solved it, the problem was in the style declaration for the DataGridTemplateColumn.
Despite setting toggle button background to Transparent it was not working as Raviraj suggested.
Finally the solution was to change the piece of code regarding to the DataGridTemplateColumn:
<dg:DataGridTemplateColumn.CellStyle>
<Style TargetType="dg:DataGridCell">
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
</dg:DataGridTemplateColumn.CellStyle>
By this one:
<dg:DataGridTemplateColumn.CellStyle>
<Style TargetType="dg:DataGridCell">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type dg:DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</dg:DataGridTemplateColumn.CellStyle>
Doing this is working.
Below the result.
Before row selection:
After row selection:
Set the background color of your the column template to transparent.
Something like this:
<DataTemplate>
<ToggleButton Background="Transparent" Content="" IsChecked="{Binding Path=IsSelected}">

WPF apply triggers to listview items to change background

I am trying to create a sort of left menu for navigation inside the desktopapplication. My idea is to use Buttons as Listview items which should behave in this way: when i hover with the mouseover them theri background should change color (becomes darkCyan) and when i click one its background color should change persistently (to darkCyan) until i click on another button of the list. The problem is that i am using a the DataTemplate property to specify how the buttons should look like and I am tryin to apply the triggers to change the background color on the ControlTemplate of the ListView. The result is that sometimes the background color changes but the command related to the button is not fired other times the contrary. I think that I am doing the things in the wrong element of the tree view, but I don't have enough knowledge of the tree view so I am not understanding what I am doing wrong. Here is the code of the XAML in which i define the styles for the Buttons and the ListView
<Window.Resources>
<DataTemplate DataType="{x:Type viewModels:TripViewModel}">
<views:TripView />
</DataTemplate>
<Style TargetType="{x:Type Button}">
<Setter Property="Height"
Value="50" />
<Setter Property="Background"
Value="#555D6F" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border>
<Grid Background="Transparent">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border BorderBrush="Transparent"
BorderThickness="0"
Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Background"
Value="DarkCyan" />
</Trigger>
<Trigger Property="IsSelected"
Value="True">
<Setter Property="Background"
Value="DarkCyan" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
And here is the code in which I create the ListView
<ListView Name="MenuButtons"
ItemsSource="{Binding PageViewModels}"
Background="Transparent"
IsSynchronizedWithCurrentItem="True">
<ListView.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Name}"
Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
Margin="0" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Anyone can help?
Thanks
I have solved the issue by using a ListBox instead of a ListView and setting the ItemContainer to be a button in the following way
<ListBox.ItemTemplate>
<ItemContainerTemplate>
<Button Content="{Binding Name}"
Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
Margin="0" />
</ItemContainerTemplate>
</ListBox.ItemTemplate>

How to style a custom TabItem's Header in a style's trigger?

Following my first question, I'm left with the following XAML:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TabControl>
<TabControl.Resources>
<Style TargetType="{x:Type TabItem}">
<Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Border BorderBrush="Transparent" Background="Transparent">
<ContentPresenter x:Name="TabItemContent" VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Header" Margin="12,2,12,2" RecognizesAccessKey="True"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="TextElement.Foreground" Value="DarkOrange" TargetName="TabItemContent"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.Resources>
<TabItem>
<TabItem.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="First"/>
<TextBlock Text="Tab"/>
</StackPanel>
</TabItem.Header>
<TextBlock Text="TextBlock"/>
</TabItem>
<TabItem Header="TAB2">
<TextBlock Text="TextBlock too"/>
</TabItem>
</TabControl>
</Grid>
</Window>
The styling works well for the second tab (which has a simple Header), but doesn't for the first one (with a 'complex' header).
Is there a way to bypass this behavior? I can't think of one myself; I tried replacing the "TextElement" by "TabItem" with no success.
EDIT: removed irrelevant XAML parts.
Yes, this is a difficult problem; inheritance works by the logical tree, and the logical parent of the complex header is the TabItem. If you set the Foreground on a TabItem, the content of the tabitem will inherit that foreground as well, and that is something that you don't want.
Luckily there is a simple solution: put the UI in a HeaderTemplate instead of the Header property. The root of the template doesn't have a logical parent, but it does have the ContentPresenter as its TemplatedParent, and apparently inheritance also propagates from templated parent to the root in the template.
So I came up with a somewhat elegant solution, even though extremely limited (it will only be usable if your custom headers only are meant to contain 2 text elements, if you want more, this won't work, although it doesn't seem impossible to replace a TextBlock by a Image; but yeah, 2 elements).
I just added a HeaderTemplate setter in the TabItem's Style, and do my dark bidings here, binding to Tag to get the name of the tab.
Here's how it goes:
<Style TargetType="{x:Type TabItem}">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Tag, RelativeSource={RelativeSource AncestorType=TabItem}}" Margin="2,0"/>
<TextBlock Text="{Binding}" Margin="2,0"/>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<ContentPresenter x:Name="TabItemContent" ContentSource="Header" HorizontalAlignment="Center" Margin="4" RecognizesAccessKey="True"/>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="TabItemContent" Property="TextElement.Foreground" Value="DarkOrange"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And how it's used (placing the above Style in your Window/UserControl/TabControl's resources):
<TabItem Header="{Binding SomeValue}" Tag="TabName">
<some:Controls/>
</TabItem>
Due to the use of a StackPanel, if SomeValue is null, your TabItem will only show "TabName".

ListView Style Trigger affecting one control and not another

I have a ListView control with a list of system messages in it, and a corresponding "action" button that will help my user resolve the message:
If the message is an error message, I want the Foreground of the text and the action button (the [more...] part) to turn red. As you can see, it's not doing that.
I'm using a Style.Trigger bound to the message data's Severity to set the Foreground. This works fine for the TextBlock in the DataTemplate, but fails to affect the Button in that Template. My XAML looks like this:
<ListView x:Name="ImageCenterStatus" Background="{DynamicResource SC.ControlBrush}" Margin="10,22,10,0" FontSize="12" Grid.Column="1" ClipToBounds="True" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock TextWrapping="WrapWithOverflow" cal:Message.Attach="[Event MouseUp] = [Action DoStatusAction($dataContext)]" Text="{Binding Path=DisplayedMessage}"/>
<Button x:Name="ActionButton" Content="{Binding Path=DisplayedActionLabel}" FontSize="12" cal:Message.Attach="DoStatusAction($dataContext)" Style="{DynamicResource SC.ActionButtonHack}"></Button>
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Severity}" Value="Warning">
<Setter Property="Foreground" Value="#FFCE7A16" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=Severity}" Value="Error">
<Setter Property="Foreground" Value="#FFD13636" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
</ListView>
The Button has its own Style, SC.ActionButtonHack, but I am very careful not to override the Foreground anywhere that style:
<Style x:Key="SC.ActionButtonHack" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<ContentPresenter x:Name="contentPresenter" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Why does the TextBlock in the DataTemplate respond to the Foreground change in the Trigger, but not the Button?
What do I need to do to get the button to respect the Foreground change?
Bind TextElement.Foreground of ContentPresenter to ListViewItem's foreground to get it work:
<Style x:Key="SC.ActionButtonHack" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<ContentPresenter x:Name="contentPresenter"
TextElement.Foreground="{Binding Foreground,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=ListViewItem}}"
HorizontalAlignment="Center"
VerticalAlignment="Center" Margin="0"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
OR
Either bind it on Button itself:
<Button x:Name="ActionButton"
Foreground="{Binding Foreground, RelativeSource={RelativeSource
Mode=FindAncestor, AncestorType=ListViewItem}}"
Content="{Binding Path=Name}" FontSize="12"
Style="{DynamicResource SC.ActionButtonHack}"/>

WPF - Setting ToolTip MaxWidth

I would like to set ToolTip maxwidth property to show long texts properly. In addition I need text wrapping. I used this style:
<Style TargetType="ToolTip">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding}" MaxWidth="400" TextWrapping='Wrap' />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
This tooltip style is OK for my purpose. However, it is not effective for some controls which has own tooltip style. For example, tooltip of following button can not appear.
<Button>
<Button.ToolTip>
<StackPanel>
<TextBlock Style="{StaticResource firstText}" Text="aaaaaaaaaaaaa"/>
<TextBlock Style="{StaticResource secondText}" Text="bbbbbbbbbbbbb"/>
<TextBlock Bacground="Red" Text="ccccccccccccc"/>
</StackPanel>
</Button.ToolTip>
</Button>
I want to set maxwidth property with text wrapping for all tooltips. What can i do for this issue?
I avoid using Template because a lot things must be implement. So more elegant way to do that
<Style TargetType="ToolTip">
<Style.Resources>
<Style TargetType="ContentPresenter">
<Style.Resources>
<Style TargetType="TextBlock">
<Setter Property="TextWrapping" Value="Wrap" />
</Style>
</Style.Resources>
</Style>
</Style.Resources>
<Setter Property="MaxWidth" Value="500" />
</Style>
I realise that this is an old question, but no one seems to have suggested the most obvious and simplest solution to this problem yet. As such, I thought I'd add it here:
<Button>
<Button.ToolTip>
<ToolTip MaxWidth="400">
<TextBlock Text="{Binding Binding}" TextWrapping="Wrap" />
</ToolTip>
</Button.ToolTip>
</Button>
Following style of ToolTip is useful for me:
<Style TargetType="ToolTip" x:Key="InternalToolTipStyle">
<Setter Property="MaxWidth" Value="{Binding Path=(lib:ToolTipProperties.MaxWidth)}" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<ContentPresenter Content="{TemplateBinding Content}" >
<ContentPresenter.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="TextWrapping" Value="Wrap" />
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
With this style, tooltip of following button appears properly:
<Button>
<Button.ToolTip>
<StackPanel>
<TextBlock Style="{StaticResource firstText}" Text="aaaaaaaaaaaaa"/>
<TextBlock Style="{StaticResource secondText}" Text="bbbbbbbbbbbbb"/>
<TextBlock Bacground="Red" Text="ccccccccccccc"/>
</StackPanel>
</Button.ToolTip>
Use this:
<Window.Resources>
<Style TargetType="ToolTip" x:Key="TT">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding}" MaxWidth="400" TextWrapping='Wrap' />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Button>
<Button.ToolTip>
<ToolTip Style="{StaticResource TT}">
bbbbbbbbbbbbbbbbbbbdddddddddddddddddbbbmmmmmmhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
</ToolTip>
</Button.ToolTip>
</Button>
Edit:
<Button>
<Button.ToolTip>
<RichTextBox>
<FlowDocument>
<Paragraph>
This is flow content and you can <Bold>edit me!</Bold>
</Paragraph>
</FlowDocument>
</RichTextBox>
</Button.ToolTip>
</Button>
see :RichTextBox Overview

Resources