Change fontweight on button in WPF treeview - c#

I have a templated treeview that is working just as i want, but i have a context menu which allows for a tier 1 node to be marked as "default".
I have a datatrigger which reacts to a property in the viewmodel, which should change the fontweight to bold just to visually show that this is the default node. But the setter will not change the fontweight on the button no matter what!
However if i change another value, like the foreground color for example, it works just fine, font size also no problem.
Why is this, can anyone explain this? Here is some code if needed:
Trigger:
<HierarchicalDataTemplate ItemsSource="{Binding Children,Mode=TwoWay,NotifyOnSourceUpdated=True}">
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
<Image x:Name="nodeImg" Source="{Binding Image}" MaxHeight="16" MaxWidth="16"/>
<Button x:Name="nodeButton" Content="{Binding Name}" Command="{Binding Command}" Style="{StaticResource TreeMenuButton}"/>
</StackPanel>
<HierarchicalDataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=TreeViewItem},Path=IsExpanded}" Value="True">
<Setter TargetName="nodeImg" Property="Source" Value="{Binding ImageExpanded}"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding IsDefaultConnection}" Value="True">
<Setter TargetName="nodeButton" Property="FontWeight" Value="Bold"></Setter>
</DataTrigger>
</HierarchicalDataTemplate.Triggers>
</HierarchicalDataTemplate>
Default style on button:
<Style x:Key="TreeMenuButton" TargetType="{x:Type Button}">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="MinHeight" Value="23" />
<Setter Property="MinWidth" Value="75" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="Border"
CornerRadius="0"
BorderThickness="0"
Background="Transparent"
BorderBrush="Transparent">
<ContentPresenter Margin="2"
HorizontalAlignment="Left"
VerticalAlignment="Center"
RecognizesAccessKey="True"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

I'd be surprised if your code even built as you can't add a DataTrigger into a UIElement.Triggers collection. Try using a Style instead (this definitely works):
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding IsDefault}" Value="True">
<Setter Property="TextBlock.FontWeight" Value="Bold" />
</DataTrigger>
</Style.Triggers>
</Style>
If by some miracle your DataTemplate does work in a UIElement.Triggers collection, then try using the class name as well as the property name:
<Setter Property="TextBlock.FontWeight" Value="Bold" />

Related

Add style to border (parent element) when checkbox is selected WPF

I'm trying to add differences style to the border when the radio button is checked and not checked. Is there anyway to do this in xaml with binding?
<Border
Width="672"
Height="122"
HorizontalAlignment="Left">
<RadioButton
Margin="0,0,0,8"
HorizontalAlignment="Left"
VerticalAlignment="Top"/>
</Border>
This is what i'm doing now but it doesnt work for me yet
<Border.Style>
<Style TargetType="{x:Type Border}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Child.Children[0].IsChecked}" Value="true">
<Setter Property="Background" Value="red" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>

Removing the 'selection' from a radio button in a listview control

This feels like the solution would be obvious, but apparently not.
I've got a listview on my window defined like so:
<ListView SelectedValue="{Binding Gender, ValidatesOnDataErrors=True}" Grid.Column="1" Grid.Row="3" SelectedValuePath="Tag" BorderThickness="0" Margin="2" SelectionMode="Single">
<RadioButton GroupName="Gender" Margin="2" Tag="M" Content="Male" IsChecked="{Binding RelativeSource={RelativeSource AncestorType=ListViewItem}, Path=IsSelected}"/>
<RadioButton GroupName="Gender" Margin="2" Tag="F" Content="Female" IsChecked="{Binding RelativeSource={RelativeSource AncestorType=ListViewItem}, Path=IsSelected}"/>
</ListView>
When one of those radio buttons is selected, it has a grey background and border around the item. I want to remove/hide the background and border. How do I do this?
I've tried setting Focusable to false. Various styles, templates, triggers etc. but these have no effect. I tried all solutions from this question but they didn't work.
How else can I remove this styling on the list view items. Basically I want the grey background and border gone when the control doesn't have focus.
EDIT: Adding a picture to illustrate what I'm trying to achieve. I want the border and background around the 'Male' radiobutton removed/hidden. So this is what I have:
And this is what I want:
This is what I think should work (according to answers so far, but does nothing. The style just stays the same.)
<!-- This doesn't change the style... -->
<ListView.Resources>
<Style TargetType="ListViewItem">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Background" Value="Transparent"/>
</Trigger>
</Style.Triggers>
</Style>
</ListView.Resources>
<!-- Neither does this... -->
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True"/>
<Condition Property="IsFocused" Value="False"/>
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Foreground" Value="{x:Null}"/>
<Setter Property="Background" Value="{x:Null}"/>
<Setter Property="BorderBrush" Value="{x:Null}"/>
</MultiTrigger.Setters>
</MultiTrigger>
</Style.Triggers>
</Style>
You' should add a style trigger:
<Style TargetType="RadioButton">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="YOUR FAVORITE COLOR HERE" />
<Setter Property="BorderBrush" Value="YOUR FAVORITE COLOR HERE"/>
</Trigger>
</Style.Triggers>
</Style>
I made reference to this: www.wpf-tutorial.com/styles/trigger-datatrigger-event-trigger/
This is just an example to show you the right way! Hope it helps
Ok, I have no idea what I've done, but I found the answer my tweaking the XAML in this blog post:
I've ended up with this Style, I have no idea what it does, but it does what I want it to do.
The full XAML for my ListView now looks like this, I'll move the style into a resource dictionary later.
<ListView SelectedValue="{Binding Gender, ValidatesOnDataErrors=True}" Grid.Column="1" Grid.Row="3" SelectedValuePath="Tag" BorderThickness="0" Margin="2" SelectionMode="Single">
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="Bd"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive"
Value="False" />
<Condition Property="IsSelected"
Value="True" />
</MultiTrigger.Conditions>
<Setter Property="Background"
TargetName="Bd"
Value="Transparent" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.Resources>
<RadioButton GroupName="Gender" Margin="2" Tag="M" Content="Male" IsChecked="{Binding RelativeSource={RelativeSource AncestorType=ListViewItem}, Path=IsSelected}"/>
<RadioButton GroupName="Gender" Margin="2" Tag="F" Content="Female" IsChecked="{Binding RelativeSource={RelativeSource AncestorType=ListViewItem}, Path=IsSelected}"/>
</ListView>

Change usercontrol border on its GotFocus-event within the XAML of a WPF-Project

I have a UserControl, which contains a Grid which contains a Border:
<UserControl Focusable="True" Name="uctrlScenePanel">
<Grid MouseDown="Grid_MouseDown">
<Border BorderThickness="0" BorderBrush="Black">
</Border>
</Grid>
I now wanted to change the Border-Thickness once the usercontrol "uctrlScenePanel" got Focus, but i can't get it to work and i dont really find useful Eventtrigger-Tutorials which a can understand, because i am very new to WPF.
edit:
d.moncada's answer was very helpful! my xaml now looks like this:
<Border BorderBrush="Black">
<Border.Style>
<Style TargetType="Border">
<Setter Property="BorderThickness" Value="0" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsKeyboardFocusWithin, ElementName=uctrlScenePanel}" Value="true">
<Setter Property="BorderThickness" Value="2" />
<Setter Property="Background" Value="Green" />
</DataTrigger>
<DataTrigger Binding="{Binding IsKeyboardFocusWithin, ElementName=uctrlScenePanel}" Value="false">
<Setter Property="BorderThickness" Value="0" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
I have still problems,because the focusing of a user control behaves weird, but thats another story...this one is solved for me, thanks for the lesson ;)
You can bind to the UserControl IsFocused property using a DataTrigger.
<UserControl Focusable="True" x:Name="uctrlScenePanel">
<Grid MouseDown="Grid_MouseDown">
<Border BorderBrush="Black">
<Broder.Style>
<Style TargetType="Border">
<Setter Property="BorderThickness" Value="1"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsFocused, ElementName=uctrlScenePanel}" Value="True">
<Setter Property="BorderThickness" Value="0"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
</Grid>
</UserControl>

Use an image for a menu option in WPF

I use the following XAML to achieve a menu using radio buttons:
<Grid.Resources>
<Style TargetType="{x:Type RadioButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<TextBlock Text="{TemplateBinding Content}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="White" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, RelativeSource={RelativeSource AncestorType={x:Type RadioButton}}}" Value="True">
<Setter Property="Foreground" Value="Gold" />
</DataTrigger>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type RadioButton}}}" Value="True">
<Setter Property="Foreground" Value="Gold" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<StackPanel Margin="25,74,644,78" Background="{x:Null}">
<RadioButton Content="1. Do something." Click="RadioButton1_Click" FontSize="16" Margin="5"/>
<RadioButton Content="2. Do something else." Click="RadioButton2_Click" FontSize="16" Margin="5"/>
</StackPanel>
This works fine but I want to include an image as a menu option instead of text. (The image is for 'Home' and it will have a normal image and a hover over image)
Here is what I want to achieve:
How do I do this?
You can define another style for displaying Radio Button as an Image based on the existing style posted in question, just need slight changes in ControlTemplate's content part. Following is an example of such a Style and the usage :
<StackPanel Orientation="Horizontal" Background="Black">
<StackPanel.Resources>
<Style x:Key="PictSTyle" TargetType="{x:Type RadioButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<Image Width="50" Height="50">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="home_default.png" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type RadioButton}}}" Value="True">
<Setter Property="Source" Value="home_hovered.png" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</StackPanel.Resources>
<RadioButton Margin="5" Style="{StaticResource ResourceKey=PictSTyle}"/>
</StackPanel>
To give a menu item an image:
<MenuItem>
<MenuItem.Icon>
<Image Source=""/>
</MenuItem.Icon>
</MenuItem>
for your trigger just change the MenuItem's icon to the "highlighted one", when the user hovers over the menu item (IsMouseOver), by changing the Icon's image source.
Put an image element as the "Content" property for your radio button
<RadioButton Click=HomRadioButtonClick>
<RadioButton.Content>
<Image Source=""/>
</RadioButton.Content>
</RadioButton>
You'll need some extra logic for the hover behavior, but that should at least get the image in your menu.

Wpf listbox itemstlye triggers not working

I am using a listbox itemstyle and triggers to change the mouseover color but the style does not seem to work:
<ListBox ItemsSource="{Binding LocationItems}" SelectionChanged="RadListBox_SelectionChanged" Name="RLBLocations">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="BorderBrush" Value="#FF709A70"/>
<Setter Property="Height" Value="50"/>
<Setter Property="Width" Value="200"/>
<Setter Property="Foreground" Value="#FF5C5C5C"/>
<Setter Property="FontFamily" Value="Franklin Gothic Book"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<StackPanel Orientation="Horizontal" Height="50">
<Image Source="{Binding Icon}" Margin="0" Stretch="UniformToFill" Width="32" Height="32"/>
<TextBlock Margin="10,10,0,0" Text="{Binding Text.Text}" Foreground="Black" TextAlignment="Left"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ToolTip" Value="{Binding ToolTip}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Background" Value="#FFF0F0F0"/>
<Style.Triggers>
<DataTrigger Binding="{Binding
RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorType={x:Type ListBoxItem}},
Path=IsMouseOver}" Value="True">
<Setter Property="Background" Value="#FF709A70"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
I get this error in the output window:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ListBoxItem', AncestorLevel='1''. BindingExpression:Path=IsMouseOver; DataItem=null; target element is 'ListBoxItem' (Name=''); target property is 'NoTarget' (type 'Object')
I understand that the error but need help trying figure out the style - I have tried doing it with a datatemplate and that did not work out either.
Your DataTrigger:
<DataTrigger Binding="{Binding RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorType={x:Type ListBoxItem}},
Path=IsMouseOver}"
Value="True">
<!-- ... -->
</DataTrigger>
Is trying to find the Ancestor (of Type ListBoxItem) of the ListBoxItem. Of course that doesn't exist unless you nest ListBoxItems inside of each other.
Change it to this:
<Trigger Property="IsMouseOver" Value="True">
<!-- ... -->
</Trigger>
Also, you're overriding the ListBoxItem's Template, and in your custom template there's nothing pointing to the ListBoxItem.Background property, that brush will never be visible on screen.
I suggest you use it for the StackPanel's Background:
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<StackPanel Orientation="Horizontal" Height="50" Background="{TemplateBinding Background}">
<!-- ... -->
</StackPanel>
</ControlTemplate>
Also, I think you might be confusing the concept of ListBoxItem.Template with ListBox.ItemTemplate, which is a DataTemplate used to render your Data inside regular ListBoxItems. I suggest you take a look at this tutorial for more info.

Categories