ContentControl switch between two buttons - c#

I've been banging my head over this all night. All I want to do is have a content control that can switch between showing two different buttons according to a boolean in the ViewModel.
Basically I have a task running in the background with a cancel button. Once you hit cancel and the task stops, the cancel button should change to a back button. These are two separate button elements, not just changing a single button's properties. I'm using MahApps TransitioningContentControl so I want to be able to use the transitions.
I would be amazing if this could mostly be done all in XAML. I really don't want to have to add a bunch of boilerplate code for what should be a simple thing.
Edit: Here's the snippet of code. There isn't much because I just deleted everything that wasn't working.
<Controls:TransitioningContentControl x:Name="CancelBackButtonControl" HorizontalAlignment="Left" VerticalAlignment="Top" Width="80" Height="80">
<Canvas>
<Button x:Name="CancelButton" HorizontalAlignment="Left" VerticalAlignment="Top" Width="80" Style="{DynamicResource MetroCircleButtonStyle}" Height="80" IsCancel="True" Content="{StaticResource appbar_close}" BorderBrush="Black" Command="{Binding CancelCommand}"/>
<Button x:Name="GoBackButton" HorizontalAlignment="Left" VerticalAlignment="Top" Width="80" Style="{DynamicResource MetroCircleButtonStyle}" Height="80" IsCancel="True" Content="{StaticResource appbar_arrow_left}" BorderBrush="Black" Command="{Binding GoBackCommand}"/>
</Canvas>
</Controls:TransitioningContentControl>

There are a staggering amount of ways to accomplish this (that's the beauty of WPF); however, in my personal opinion, you would be working less "against the grain" if you simply use a control that derives from the ToggleButton, such as RadioButton, especially since you want it to be done all in XAML. An important thing is not to think of any of the controls by their visuals, but by how they function. I've done some incredible things with RadioButton before, so that's the first thing I'll demonstrate; however, the regular button approach is included in the second half of this answer.
Here are the complete examples of both approaches (RadioButton and Button), done completely in XAML:
Preview:
Code:
<Window x:Class="Sample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="{x:Type RadioButton}" x:Key="FlatRadioButtonStyle">
<Setter Property="Width" Value="100"/>
<Setter Property="Background" Value="#FF346FD6"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Padding" Value="5,2,5,3"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<Border Background="{TemplateBinding Background}"
Width="{TemplateBinding Width}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}">
<ContentPresenter Content="{TemplateBinding Content}"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#FF6696E9"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Visibility" Value="Collapsed"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<RadioButton x:Name="BackButton" Content="Back">
<RadioButton.Style>
<Style TargetType="{x:Type RadioButton}" BasedOn="{StaticResource FlatRadioButtonStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=CancelButton}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</RadioButton.Style>
</RadioButton>
<RadioButton x:Name="CancelButton" Content="Cancel" IsChecked="True">
<RadioButton.Style>
<Style TargetType="{x:Type RadioButton}" BasedOn="{StaticResource FlatRadioButtonStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=BackButton}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</RadioButton.Style>
</RadioButton>
</Grid>
</Window>
Most of the resource style code is visual styling and templating, focused on making radio buttons look like regular buttons, so it's not of great importance. The areas we'll focus on are Triggers. You'll notice that in the resource style, I ensure that when a RadioButton gets checked, it collapses. However, in the local style of each button, I ensure that when the other RadioButton gets checked, it makes the current RadioButton visible. This has to be done in the local style, since we need to pass the ElementName into the Binding. So, when a RadioButton gets checked, it collapses and makes the other RadioButton visible. You'll also note that I check the button I wish to hide by default. Obviously, you can wire that up with bindings.
Similar approaches may be applied to regular buttons:
Preview:
Code:
<Window x:Class="Sample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="{x:Type Button}" x:Key="ToggleButtonStyle">
<Setter Property="Width" Value="100"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Visibility" Value="Collapsed"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Button x:Name="CancelButton" Content="Cancel">
<Button.Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource ToggleButtonStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsFocused, ElementName=BackButton}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<Button x:Name="BackButton" Content="Back">
<Button.Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource ToggleButtonStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsFocused, ElementName=CancelButton}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</Grid>
</Window>
Here, instead of IsChecked, I'm working with IsFocused. You may accomplish a similar thing by working with the EventTrigger and Click event... but, there's more work. IsPressed may appear like a good candidate, but the problem is that once you press the button, the other one will appear almost instantaneously, and that one will have IsPressed set to true almost instantaneously. So, you'll end up with this cyclic behavior where it seems like nothing is happening. Note that I use Grid to place these buttons on top of each other, with the the one I want to be visible by default at the top, that way I don't have to worry about default visibility or focus. However, you may use any other panel, just set the Visibility of the button you want to hide by default to Collapsed.
If you don't want to work with multiple controls (two buttons in this case), you may also set the Content property of a button based on a condition through DataTrigger to display different text. You just have to ensure that you handle the Command appropriately.

Since you're asking for a XAML only way to switch the button in a content control based on a ViewModel property, how about this:
First define button style to route both buttons to the same event:
<Style x:Key="buttonClickButton" TargetType="Button">
<EventSetter Event="Click" Handler="Button_Click"/>
</Style>
Then define your content control style with a data trigger switching the content based on a ViewModel property called "IsCancelButton" (bool):
<Style x:Key="ButtonSwitchContentCtrl" TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding IsCancelButton}" Value="True">
<Setter Property="Content">
<Setter.Value>
<Button x:Name="CancelButton" Style="{StaticResource buttonClickButton}"
HorizontalAlignment="Left" VerticalAlignment="Top"
Width="80" Height="80" IsCancel="True" Content="Cancel Button" BorderBrush="Black" />
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding IsCancelButton}" Value="False">
<Setter Property="Content">
<Setter.Value>
<Button x:Name="GoBackButton" Style="{StaticResource buttonClickButton}"
HorizontalAlignment="Left" VerticalAlignment="Top"
Width="80" Height="80" IsCancel="True" Content="Go Back Button" BorderBrush="Black" />
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
Then make your button(s) appear like so:
<ContentControl Style="{StaticResource ButtonSwitchContentCtrl}"/>

You can implement such functionality with just one Button (e.g. declared in XAML as Name="btnCancel") and simple code snippet in C# code-behind using Lambda-style event subscription like:
btnCancel.Click+=(s,e)=>{
if (btnCancel.Text=="Cancel")
{
// SOME CODE CORRESPONDING TO "CANCEL" CLICK EVENT
btnCancel.Text ="GoBack"
}
else
{
// CORRESPONDING TO "GoBack" CLICK EVENT
btnCancel.Text ="Cancel"
}
}
In case you want to use some graphic content (images) on the Button, then use Tag property of that Button instead of Text and also programmatically switch between images.
Couple other considerations: the business logic you have described could be implemented in XAML using DataTriggers (as other folks did), but instead of writing megaton of XAML for 2-Buttons solutions it would be reasonable to implement a single-button solution, either like this one, or using .NET ToggleButton Class (re: https://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.togglebutton%28v=vs.110%29.aspx); also, it could be a CheckBox control just properly styled.
In any way, you most likely will need the event handlers to do some actual job in addition to just changing the visual state of the Button, so that compact Lambda-style event subscription would be handy.
Hope this may help. Best regards,

Related

C# WPF Dynamic Button STYLE that has different pictures based on the x:name or x:key they have

I would like to make a game like Shakes & Fidgets. I got stuck at the Main menu, where I already overcomplicated stuff as I always do. I made a grid layout, where I will put the buttons, but every button is a picture. I use ImageBrush for every button's picture I want to create.
I would like to create ONE style for every button so they change their backgrounds based on the x:Name or x:Key they have. So a Button with x:Name or x:Key "PlayGame" would find it's as the PlayGame.png, PlayGame_Hover, PlayGame_OnClick where "PlayGame" is a variable.
In other words I would like to have a style that can filter the x:name, or x:key of a button, and uses it as a variable later on so I can do this: {StaticResource VARIABLENAME}
The Code I have now is:
<ImageBrush x:Key="PlayGame">
<ImageBrush.ImageSource>
<BitmapImage UriSource="./Pictures/PlayGameButton.png"/>
</ImageBrush.ImageSource>
</ImageBrush>
<ImageBrush x:Key="PlayGame_Hover">
<ImageBrush.ImageSource>
<BitmapImage UriSource="./Pictures/PlayGameButton_Hover.png"/>
</ImageBrush.ImageSource>
</ImageBrush>
<ImageBrush x:Key="PlayGame_OnClick">
<ImageBrush.ImageSource>
<BitmapImage UriSource="./Pictures/PlayGameButton_OnClick.png"/>
</ImageBrush.ImageSource>
</ImageBrush>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="{StaticResource PlayGame}" />
<Setter Property="FontSize" Value="15" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border CornerRadius="4" Background="{TemplateBinding Background}">
<Grid>
<ContentPresenter x:Name="MyContentPresenter" Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource PlayGame_Hover}" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="{StaticResource PlayGame_OnClick}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I found a not very effective solution, but not the one I actually want
You can give the Style an
x:Key="styleKey"
and you have to give the button this part:
Style="{StaticResource styleKey}"
This way you will have to make a style for every different button you want to have, but it will work, and you will be happy about it if efficency is not key.:D

TemplatedParent is null when used inside a ControlTemplate's DataTrigger

Consider this (edited-down) Style, designed for a Button whose Content is a String:
<Style x:Key="Test" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<StackPanel>
<TextBlock x:Name="text" Text="{TemplateBinding Content}" />
<TextBlock x:Name="demo" Text="{Binding RelativeSource={RelativeSource TemplatedParent}}" />
</StackPanel>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}">
<DataTrigger.Value>
<system:String>Test</system:String>
</DataTrigger.Value>
<Setter TargetName="test" Property="Foreground" Value="Red" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The intention in this example is to turn the button text red if it equals the word "Test"1. But it doesn't work, because the trigger's TemplatedParent binding resolves to null instead of to the Button the Style is applied to. However, the TextBlock named "demo" will have its Text set to "System.Windows.Controls.Button: [ButtonText]" as expected, which means TemplatedParent works correctly at that level. Why doesn't it work inside the DataTrigger?
1 I know there are other ways to achieve that, but I'm trying to understand why the binding doesn't work the way I expect it to.
TemplatedParent in your ControlTemplate.Triggers is not what you expect. Inside trigger it actually references Button.TemplatedParent. As such, it will only be non-null if your create that button inside template. You don't create button inside template, so it is null in your case. Now consider this xaml:
<Window.Resources>
<Style x:Key="Test"
TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<StackPanel>
<TextBlock x:Name="text"
Text="dummy" />
<TextBlock x:Name="demo"
Text="{Binding RelativeSource={RelativeSource TemplatedParent}}" />
</StackPanel>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}">
<DataTrigger.Value>
<system:String>Test</system:String>
</DataTrigger.Value>
<Setter TargetName="text"
Property="Foreground"
Value="Red" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="Test2" TargetType="ContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Button Style="{StaticResource Test}"></Button>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<!--<Button Content="Test" Style="{StaticResource Test}"/>-->
<ContentControl Style="{StaticResource Test2}" Content="Test" />
</Grid>
Here I retemplate ContentControl and inside template I use button with your template. If you run this code, you will see "dummy" text in red, because Button.TemplatedParent is now ContentControl, and it has it's Content equals "Test", which confirms what I said above.
Now back to your problem: just change RelativeSource TemplatedParent to RelativeSource Self (no need to change DataTrigger to Trigger) - this one would reference your Button.
I think it might be a similar issue in .NET Core WPF.
My DataTrigger was not firing with {Binding MyProp, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource Convert}}, but instead when I changed the RelativeSource to Self the binding started to work. I'm not sure whether it's a hack or a solution, but it worked.
Maybe it's worth mentioning that my template was based on MyView (see below) and I was binding to a DependencyProperty on MyView.
So my final code looked like this:
<ControlTemplate x:Key="Template" TargetType="{x:Type ns:MyView}">
<!-- Some template -->
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding MyProp, RelativeSource={RelativeSource Self}, Converter={StaticResource Convert}}" Value="True">
<Setter Property="Foreground" Value="Red"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
I'm not quite sure, but I think the trigger equals by referenc, because Content returns an Object. So it will never be true with your string defined within the trigger.

ToggleButton Style only works on last ToggleButton

I'm trying to customize my ToggleButtons so that when checked they say 'Yes' in green and when not checked, say 'No' in red.
I've created the following style which is sitting in my Styles resource dictionary.
<!-- ToggleButtons -->
<Style x:Key="YesNoToggleStyle" TargetType="ToggleButton">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="SpringGreen" />
<Setter Property="Content">
<Setter.Value>
<TextBlock Text="Yes"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Background" Value="Crimson" />
<Setter Property="Content">
<Setter.Value>
<TextBlock Text="No"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
This works ... sort of. If the ToggleButton is the last one of either value, then it displays correctly. All previous buttons with the same value are blank. The height was also shrinking, but I fixed that with the 'Height' Setter above the triggers. To illustrate, when a new record is being created it looks like:
and after I've clicked buttons 1, 2, and 3 and 1 again:
I originally had the style referenced from the surrounding grid:
<Grid>
...
<Grid.Resources>
<Style BasedOn="{StaticResource YesNoToggleStyle}" TargetType="{x:Type ToggleButton}" />
</Grid.Resources>
But changing that so each ToggleButton references the style individually (<ToggleButton Style="{StaticResource YesNoToggleStyle}" ... />) hasn't made a difference.
I looked at Customizing the toggle state of a toggle button in wpf, and Override ToggleButton Style where the effect is the same, but they talk about external images, and my issues is all within wpf.
I also looked at the second answer to: i want to change backcolor of toggle button when toggle button ischecked and viceversa in WPF but a) I only have the blend + sketchflow preview that comes with VS2012, and b) i'm a total noob with blend and can't get from Select the "Checked State" to Reset the Background Color instruction in the answer (plus i'd be surprised if this task requires the blend tool).
Can anyone show me what to do to get multiple ToggleButtons to use the same style properly?
This works for me. Somewhere in Dictionary1.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="YesNoToggleStyle" TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource {x:Static ToolBar.ToggleButtonStyleKey}}">
<Style.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Background" Value="Crimson" />
<Setter Property="Content" Value="No"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="SpringGreen" />
<Setter Property="Content" Value="Yes"/>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
Note, that style is based on ToolBar.ToggleButtonStyle.
<Grid>
<Grid.Resources>
<ResourceDictionary Source="pack://application:,,,/Dictionary1.xaml"/>
</Grid.Resources>
<ItemsControl ItemContainerStyle="{StaticResource YesNoToggleStyle}">
<ToggleButton />
<ToggleButton />
<ToggleButton />
</ItemsControl>
</Grid>
try to replace Content property to ContentTemplate:
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="Yes"/>
</DataTemplate>
</Setter.Value>
</Setter>
In my case I wanted to have a "Locked" ToggleButton in a common dll defined and reused across my Apps.
Here's my result, which worked for me. Maybe someone find it useful (put this in a Resourcedictionary.xaml):
<BitmapImage x:Key="LockedLock"
UriSource="/...;component/Resources/Lock_closed_16p.png" />
<BitmapImage x:Key="OpenLock"
UriSource="/...;component/Resources/Lock_open_16p.png" />
<Style x:Key="LockButton"
TargetType="ToggleButton">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Source="{DynamicResource OpenLock }"
Width="12"
Height="12"
Name="contentimage" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=ToggleButton , AncestorLevel=1, Mode=FindAncestor }, Path=IsChecked}"
Value="True">
<Setter Property="Image.Source"
TargetName="contentimage"
Value="{DynamicResource LockedLock }" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
Credits to:
Setting Button's Content to <Image> via Styles
Setter Target Name not recognized

A Sane and Simple Image Button for WPF With Triggers?

I've looked at some other Stack Overflow Questions, but none seem to give a simple solution to this.
I have a button that should be an image. On MouseOver the image changes, same as with MouseClick.
I have the code for MouseOver here:
<Button Name="btnNext" Grid.Row="3" Padding="15 3" HorizontalAlignment="Right" Click="OnButtonClick" Visibility="Hidden">
<Button.Template>
<ControlTemplate>
<Border>
<Image Width="90" Height="90">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="/resources/Button1_A.png" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Source" Value="/resources/Button1_B.png" />
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Border>
</ControlTemplate>
</Button.Template>
</Button>
This seems like an awful lot of code for something that, I feel, should be relatively simple. Is there a simpler solution that I am missing?
Well ... you define a control template - and the main benefit for defining a control template is making it reusable. Templates are rarely defined inline the element, but typically in a resource dictionary (or even in the theme dictionary, so you can have a different template for each team). If you had 3 buttons, you could use it templates like that:
<Window.Resources>
<ControlTemplate x:Key="ct" TargetType="Button">
<Border>
<Image Width="90" Height="90">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="/resources/a.png" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Source" Value="/resources/b.png" />
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Border>
</ControlTemplate>
</Window.Resources>
<StackPanel>
<Button Name="btnPrev" Padding="15,3" Click="OnButtonClick" Template="{StaticResource ct}" />
<Button Name="btnNext" Padding="15,3" Click="OnButtonClick" Template="{StaticResource ct}" />
<Button Name="btnFinish" Padding="15,3" Click="OnButtonClick" Template="{StaticResource ct}" />
</StackPanel>
There are still some opportunistic shortcuts you can take:
If you aren't doing anything with Border, you can remove it. It contributes nothing.
There is no need to modify the Button.Template and have a ControlTemplate - remove these two lines
You will end up with (6 lines shorter):
<Button Name="btnNext" Padding="15,3" HorizontalAlignment="Right" Click="OnButtonClick">
<Image Width="90" Height="90">
<Image.Style>
<Style TargetType="Image">
<Setter Property="Source" Value="/resources/a.png" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Source" Value="/resources/b.png" />
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Button>
Finally, if you want to optimize your program to number of lines - trading off engineering practices - you'll have a shorter program with MouseEnter and MouseLeave events. With 3 lines of code for each event handler in the code behind, and 3 lines of code for the <Button><Image/><Button> int the XAML file, you are with 9 lines of code.

Binding content of contentPresenter in UserControl?

I've got a UserControl which is a modified toggleButton.
I've added two String properties to it so I can change (or bind) them in blend, which I want to be the text displayed when the button is toggled. ie when checked, one string is displayed, when unchecked - the other.
Setting the text is fine, and toggling the UserControl is fine, but I don't know how to set the content of the contentpresenter from a property of the toggle by a trigger. Here's a rough look at the code:
<UserControl
x:Name="UserControl"
<UserControl.Resources>
<Style x:Key="BiTextToggleButtonWithBorder" TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid>
<Path x:Name="path"
Data="M28,0.5 L28.071953,0.50129622 28.092436,0.5 115.90756,0.5 C117.89162,0.50000113 119.5,2.5147196 119.5,5.0000013 L119.61492,36.460156 119.61432,36.857203 C117.1338,37.367692 108.82679,39.239366 106.37993,47.492391 L44.667,47.5 28.092436,47.5 4.9999995,47.5 C2.5147185,47.5 0.5,45.485283 0.5,43 L0.5,21 0.51801485,20.64324 0.5,20.0835 C0.5,9.2678322 12.812169,0.50000072 28,0.5 z"
Stretch="Fill"
<ContentPresenter
x:Name="contentPresenter"
Content="{Binding}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content" TargetName="contentPresenter" Value="{Binding whatgoeshere!?}"/>
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Content" TargetName="contentPresenter" Value="whatgoeshere!?"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
<ToggleButton
x:Name="ToggleButton"
Style="{DynamicResource BiTextToggleButtonWithBorder}"
FontSize="18.667"
Foreground="{DynamicResource WhiteText}"/>
</Grid>
</UserControl>
I can't even find the property I want to change. I've done similar bindings to objects within a UserControl before, but nothing that is in a style and in a controlpresenter.
What am I missing?
have you tried changing the {Binding} to a {TemplateBinding} ? (MSDN documentation here)

Categories