I'm trying to create a button template where the button image content changes. However, I get no image showing at all with the following code. What am I doing wrong? Setting the style directly in the Page xaml works fine.
<Style x:Key="NetworkConnectivity" TargetType="Button">
<Setter Property="Width" Value="120"/>
<Setter Property="Height" Value="120"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Opacity" Value="0.7"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Width="50">
<Image.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding NetConfig}" Value="false">
<Setter Property="Image.Source" Value="/images/Unconfigured.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding NetConfig}" Value="true">
<Setter Property="Image.Source" Value="/images/Disconnected.png"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
Not the exact solution but an alternative. Below is a excerpt from my work that shows how to switch images for buttons based on triggers. Instead of style, I use a usercontrol which is reused. The data that are bound are dependency properties. You can use data trigger. In your case assign two images, make one collapsed and on trigger toggle collapse.
<UserControl x:Class="ParameterModule.Base.Controls.ButtonWImage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ParameterModule.Base.Controls"
mc:Ignorable="d"
x:Name="UctrlButtonWImage"
d:DesignHeight="100" d:DesignWidth="100">
<Button Click="Button_Click" CommandParameter="{Binding CommandParameter, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ButtonWImage}}}" Command="{Binding Command, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ButtonWImage}}}" Cursor="Hand" >
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<StackPanel>
<Image x:Name="PrimaryImage" Source="{Binding PrimaryImage, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ButtonWImage}}}" Visibility="Visible" Stretch="UniformToFill" StretchDirection="Both"/>
<Image x:Name="SecondaryImage" Source="{Binding HoverImage, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ButtonWImage}}}" Visibility="Collapsed" Stretch="UniformToFill" StretchDirection="Both"/>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="PrimaryImage" Property="Visibility" Value="Collapsed"/>
<Setter TargetName="SecondaryImage" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
</UserControl>
Related
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>
I am trying something like this: as my form load I have one image on button (this part work fine) and one check box. When I check checkbox, the image of button should change. I have attached my xaml code with this. Please go through it and suggest changes.
<CheckBox Name="checkbox" Margin="141,148,336,147"/>
<Button Foreground="Black" Height="50" Margin="238,206,179,64">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<StackPanel Orientation="Horizontal">
<Image>
<Image.Style>
<Style>
<Setter Property="Image.Source"
Value="Images/cancel_16.ico" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=checkbox, Path=IsChecked,
RelativeSource={RelativeSource AncestorType=
{x:Type Button}}}" Value="True">
<Setter Property="Image.Source"
Value="Images/cancel_16grayscale.ico" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<ContentPresenter Content="{TemplateBinding Content}"
Margin="5,0,0,0" />
</StackPanel>
</ControlTemplate>
</Button.Template>
</Button>
Just Remove the RelativeSource and add UpdateSourceTrigger Like this in your style
<Image.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=checkbox, Path=IsChecked,UpdateSourceTrigger=PropertyChanged}"
Value="True">
<Setter Property="Image.Source"
Value="Back_jeans.jpg" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=checkbox, Path=IsChecked,UpdateSourceTrigger=PropertyChanged}"
Value="False">
<Setter Property="Image.Source"
Value="Blue_Front_Jeans.jpg" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
I've been working on a WPF application but encountered some weird behaviour when using ItemsControl to display a list of togglebuttons with binding. It works just fine when it is displaying a collection of 1 element, but when I have two elements it behaves very strange. It will not show the image of both togglebuttons at once if they are in the same state (i.e. toggled on).
The relevant XAML. I have checked that the property behind is updated correctly, but let me know if there is any code that is needed.
<ItemsControl x:Name="ServiceItemsControl" Grid.Row="0" ItemsSource="{Binding DraftMessage.Services}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ToggleButton IsChecked="{Binding Path=Selected}">
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Setter Property="Focusable" Value="False"/>
<!--Setter Property="BorderThickness" Value="0"/-->
<Setter Property="Opacity" Value="1"/>
<Setter Property="Content">
<Setter.Value>
<Image Source="{Binding Path=Service.OtherLogo}" Width="25" Height="25"/>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content">
<Setter.Value>
<Image Source="{Binding Path=Service.Logo}" Width="25" Height="25"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
You need to use a DataTrigger on the Image to change its Source property when the ToggleButton.IsChecked value is changed instead. Try this:
<DataTemplate>
<ToggleButton IsChecked="{Binding Path=IsSelected}">
<Image Width="25" Height="25">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="{Binding Service.OtherLogo}" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked,
RelativeSource={RelativeSource AncestorType={x:Type
ToggleButton}}}" Value="True">
<Setter Property="Source" Value="{Binding Service.Logo}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Setter Property="Focusable" Value="False"/>
<!--Setter Property="BorderThickness" Value="0"/-->
<Setter Property="Opacity" Value="1"/>
</Style>
</ToggleButton.Style>
</ToggleButton>
</DataTemplate>
I have a data template which defines a line to display for every NodePairViewModel drawn inside by a canvas ItemsPanel. The line colour should change when the IsChecked Property of the NodePairViewModel being represented changes as defined in the style (see below) however when this property is set the colour does not change. INotifyPropertyChanged is implemented and I have verified that this event is firing. I cannot see anything obviously wrong and the same setup works for NodeViewModels which are also drawn in the same itemspanel.
<DataTemplate DataType="{x:Type vm:NodePairViewModel}">
<Line Canvas.ZIndex="2" Name="Arc" Stroke="Blue" StrokeThickness="3"
X1="{Binding Path=NodeA.PositionX, Mode=OneWay, Converter={StaticResource NodeLinkXConverter}}"
X2="{Binding Path=NodeB.PositionX, Mode=OneWay, Converter={StaticResource NodeLinkXConverter}}"
Y1="{Binding Path=NodeA.PositionY, Mode=OneWay, Converter={StaticResource NodeLinkYConverter}}"
Y2="{Binding Path=NodeB.PositionY, Mode=OneWay, Converter={StaticResource NodeLinkYConverter}}"
MouseLeftButtonDown="Arc_MouseLeftButtonDown" MouseLeftButtonUp="Arc_MouseLeftButtonUp">
<Line.Style>
<Style TargetType="Line">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsChecked}" Value="True">
<Setter Property="Stroke" Value="Orange"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsSelected, Mode=OneWay}" Value="True">
<Setter Property="Stroke" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsRejected, Mode=OneWay}" Value="True">
<Setter Property="Stroke" Value="LightGray"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsVisited}" Value="True">
<Setter Property="Stroke" Value="LightGreen"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Line.Style>
</Line>
</DataTemplate>
<ItemsControl Name="NodeSpace" ItemsSource="{Binding GraphItems}" Margin="5" MouseMove="NodeSpace_MouseMove" MouseDown="NodeSpace_MouseDown" MouseLeftButtonUp="NodeSpace_MouseLeftButtonUp" MouseLeftButtonDown="NodeSpace_MouseLeftButtonDown" MouseRightButtonDown="NodeSpace_MouseRightButtonDown" RenderTransformOrigin="0.5,0.5" Grid.Column="1" Grid.Row="1">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Name="GraphSurface" Background="#FFFFFE"></Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left">
<Setter.Value>
<Binding Mode="OneWay" Path="PositionX" Converter="{StaticResource XInverseConverter}"/>
</Setter.Value>
</Setter>
<Setter Property="Canvas.Top">
<Setter.Value>
<Binding Mode="OneWay" Path="PositionY" Converter="{StaticResource YInverseConverter}"/>
</Setter.Value>
</Setter>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
And the IsChecked property itself
private bool ArcIsChecked = false;
public bool IsChecked
{
get
{
return ArcIsChecked;
}
set
{
ArcIsChecked = value;
RaisePropertyChanged("IsChecked");
}
}
You need to move default value from Line
<Line ... Stroke="Blue">
into Style as Setter
<Line
Canvas.ZIndex="2"
Name="Arc"
StrokeThickness="3"
X1="{Binding Path=NodeA.PositionX, Mode=OneWay, Converter={StaticResource NodeLinkXConverter}}"
X2="{Binding Path=NodeB.PositionX, Mode=OneWay, Converter={StaticResource NodeLinkXConverter}}"
Y1="{Binding Path=NodeA.PositionY, Mode=OneWay, Converter={StaticResource NodeLinkYConverter}}"
Y2="{Binding Path=NodeB.PositionY, Mode=OneWay, Converter={StaticResource NodeLinkYConverter}}"
MouseLeftButtonDown="Arc_MouseLeftButtonDown"
MouseLeftButtonUp="Arc_MouseLeftButtonUp">
<Line.Style>
<Style TargetType="{x:Type Line}">
<Setter Property="Stroke" Value="Blue"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsChecked}" Value="True">
<Setter Property="Stroke" Value="Orange"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsSelected, Mode=OneWay}" Value="True">
<Setter Property="Stroke" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsRejected, Mode=OneWay}" Value="True">
<Setter Property="Stroke" Value="LightGray"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsVisited}" Value="True">
<Setter Property="Stroke" Value="LightGreen"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Line.Style>
</Line>
according to Dependency Property Setting Precedence List style trigger is lower in hierarchy then local value so it won't be able to overwrite your default (local) value
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.