Overriding Button in XAML WPF with ControlTemplate does not display content - c#

I am a XAML newbie and was looking at this blog
http://jeremybytes.blogspot.com/2009/03/wpf-xaml-sample.html
He mentions "Notice that they do not have any content (Button1a, Button1b, etc.). This is because our template does not contain an element for the Content." I am looking to figure out how ensure the content remains even after the new button template is applied. Here is the XAML
<Page.Resources>
<ControlTemplate TargetType="Button" x:Key="targetButton">
<Canvas Width="100" Height="100" Name="mainCanvas">
<Rectangle Height="100" Width="100" Fill="Aqua" Canvas.Top="1"/>
</Canvas>
</ControlTemplate>
<Style TargetType="Button">
<Setter Property="Margin" Value="5, 5, 5, 5"/>
<Setter Property="Template" Value="{StaticResource targetButton}"/>
</Style>
</Page.Resources>
<StackPanel DataContext="{Binding Board}">
<StackPanel Orientation="Horizontal">
<Button Name="testButton1a" Click="testButton1a_Click" Content="testButton1a"/>
<Button Name="testButton1b" Click="testButton1a_Click" Content="testButton1b"/>
<Button Name="testButton1c" Click="testButton1a_Click" Content="testButton1c"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button x:Name="testButton2a" Click="testButton1a_Click" Content="testButton2a"/>
<Button x:Name="testButton2b" Click="testButton1a_Click" Content="testButton2b"/>
<Button x:Name="testButton2c" Click="testButton1a_Click" Content="testButton2c"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Name="testButton3a" Click="testButton1a_Click" Content="testButton3a"/>
<Button Name="testButton3b" Click="testButton1a_Click" Content="testButton3b"/>
<Button Name="testButton3c" Click="testButton1a_Click" Content="testButton3c"/>
</StackPanel>
</StackPanel>
I have tried to add a TextBlock in the template but I see the same textblock overlayed across all buttons. All I want is to render testButton* content displayed on the rectangle button matrix so I can change the content once clicked.
Thanks, any help will be appreciated

You can use the ContentPresenter to display the content:
<ControlTemplate TargetType="Button" x:Key="targetButton">
<Canvas Width="100" Height="100" Name="mainCanvas">
<Rectangle Height="100" Width="100" Fill="Aqua" Canvas.Top="1"/>
<ContentPresenter/>
</Canvas>
</ControlTemplate>

Related

Different icons depending file type WPF in TreeView

I have goggled this and there is some information on it TreeVIew Info and Code Project which between both they were very helpful. But I still have only same type of file folders.
<Window x:Class="File_Managenment_System.File_Directory"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:uc_tools="clr-namespace:File_Managenment_System"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="File Directory"
Height="750"
Width="900"
Icon="Pictures\Icon.ico"
Background="#FF0064FF"
x:Name="frm_File_Directory"
Loaded="frm_File_Directory_Loaded">
<Grid Margin="0,0,2,-3">
<DockPanel HorizontalAlignment="Left" Height="26" LastChildFill="False" VerticalAlignment="Top" Width="840">
<uc_tools:uc_Toolbar Height="35" VerticalAlignment="Top" Width="450"/>
</DockPanel>
<TreeView x:Name="foldersItem"
Height="667"
VerticalAlignment="Top"
Margin="10,31,591,0"
Background="#FFFFFFFF"
BorderBrush="#FFFFFFFF"
Foreground="#FFFFFFFF">
<TreeView.Resources>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Name="img"
Width="20"
Height="20"
Stretch="Fill"
Source="Pictures\folder.png"/>
<TextBlock Text="{Binding}" Margin="5,0" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TreeView.Resources>
</TreeView>
</Grid>
</Window>
This is my WPF, I guess what I don't know what or how to bind to different file types.
Thanks for you help!
I don't see you datacontext, or the datasource for the tree view, but you can bind the Source property of your Image control, to a property in your model that contains the icon:
<Image Name="img"
Width="20"
Height="20"
Stretch="Fill"
Source="{Binding FolderIcon}"/>

Button content not displaying when using Control Template as Button Template WPF

So I have a circular button I have created in wpf like so:
<Button Grid.Column="3" Width="25" Height="25" Content="X" Margin="10,5,5,5" Foreground="Red" VerticalAlignment="Center" HorizontalAlignment="Center">
<Button.Template>
<ControlTemplate>
<Grid>
<Ellipse Name="Ellipse" Fill="{TemplateBinding Background}"/>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
But the button it displays is:
Why has the red X not appeared in the center of my button? and is it possible to change my xaml such that the red X will appear.
(ps. the grey background is because of my button style in my resources)
It's because there's nothing in your Template to display that Content. For that you need to use ContentPresenter
<Button Grid.Column="3" Width="25" Height="25" Content="X" Margin="10,5,5,5" Foreground="Red" VerticalAlignment="Center" HorizontalAlignment="Center">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Ellipse Name="Ellipse" Fill="{TemplateBinding Background}"/>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
you'll also need to add TargetType="{x:Type Button}" to ControlTemplate

How to remove default chrome from a WPF ToggleButton

I have a ToggleButton defined like:
<ToggleButton Name="tbPinned" Grid.Row="0" Grid.Column="3" VerticalAlignment="Bottom" HorizontalAlignment="Left" Margin="1,0,0,-5" Height="30" Width="30" IsChecked="True" Checked="tbPinned_Checked" Unchecked="tbPinned_Unchecked" >
<Image Source="/some_image.png" Stretch="Fill" />
</ToggleButton>
However, I just want the button to be an image, not an image on a button. If I was using a normal Button I would just do something like Style="{DynamicResource NoChromeButton}" in the opening ToggleButton tag. But this does not work.
How can I mimic the whole NoChromeButton thing in a ToggleButton?
EDIT: Editted to include how I do it with regular Buttons:
<Button Style="{DynamicResource NoChromeButton}" Height="17" Margin="0,0,30,0" Name="btnMinimize" VerticalAlignment="Top" Grid.Column="1" Click="btnMinimize_Click" HorizontalAlignment="Right" Width="27" Padding="0" Visibility="Visible">
<Image Source="/some_image.png" Stretch="None" />
</Button>
Just copy/paste this into new WPF project.
<Window x:Class="SOChromeButton.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 x:Key="Chromeless" TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border BorderThickness="0" Width="54" Height="54">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<ToggleButton Style="{StaticResource Chromeless}" Name="tbPinned" Grid.Row="0" Grid.Column="0" VerticalAlignment="Bottom" HorizontalAlignment="Left" Margin="10,0,0,0" IsChecked="True" >
<Image Source="C:\Temp\info.png"></Image>
</ToggleButton>
</Grid> </Window>
Will this do?
<ToggleButton Name="tbPinned" Grid.Row="0" Grid.Column="3" VerticalAlignment="Bottom" HorizontalAlignment="Left" Margin="1,0,0,-5" Height="30" Width="30" IsChecked="True" Checked="tbPinned_Checked" Unchecked="tbPinned_Unchecked"
BorderThickness="0" Background="Transparent">
<Image Source="/some_image.png" Stretch="Fill" />
</ToggleButton>

How to use an ItemTemplate on a templated control?

I am trying to create custom templated control based on a ListBox to display only the single selected item in the control's collection.
To this aim, I have defined a Template with an ContentPresenter, databound to the SelectedItem property of the control.
As illustrated in scenario 1, it works well when providing the control with a collection of UIElement.
But when needing to use a DataTemplate to display an entity object, the ItemTemplate is ignored because the control has a Template which will prevent the `ItemTemplate from being used. From what I've read this is by design and it sorts of makes sense.
But how can I use DataTemplates for my control's ItemTemplate and retain my control default template?
I have tried overriding PrepareContainerForItemOverride, and many different template configurations to no avail.
Here is some of what I tried:
<UserControl.Resources>
<local:StringCollection x:Key="MyColors">
<sys:String>Yellow</sys:String>
<sys:String>Purple</sys:String>
</local:StringCollection>
</UserControl.Resources>
<StackPanel Background="White">
<TextBlock Margin="0,25,0,0">Scenario 1: Providing UIElements to the
ControlTemplate's ContentPresenter: Works</TextBlock>
<control:RotatingFlipView x:Name="Works" SelectedIndex="1">
<control:RotatingFlipView.Template>
<ControlTemplate>
<ContentPresenter
Content="{Binding ElementName=Works, Path=SelectedItem}"/>
</ControlTemplate>
</control:RotatingFlipView.Template>
<Rectangle Height="100" Width="100" Fill="Red"/>
<Rectangle Height="100" Width="100" Fill="Blue"/>
<Rectangle Height="100" Width="100" Fill="Green"/>
</control:RotatingFlipView>
<TextBlock Margin="0,25,0,0">Scenario 2: The ItemTemplate provided is ignored in
favor of the RotatingFlipView's Template which displays the source as raw
Strings</TextBlock>
<control:RotatingFlipView x:Name="Broken"
ItemsSource="{StaticResource MyColors}">
<control:RotatingFlipView.Template>
<ControlTemplate>
<ContentPresenter
Content="{Binding ElementName=Broken, Path=SelectedItem}"/>
</ControlTemplate>
</control:RotatingFlipView.Template>
<control:RotatingFlipView.ItemTemplate>
<DataTemplate>
<Rectangle Height="100" Width="100" Fill="{Binding}"/>
</DataTemplate>
</control:RotatingFlipView.ItemTemplate>
</control:RotatingFlipView>
<TextBlock Margin="0,25,0,0">Scenario 3: Removing the RotatingFlipView's
Template, causes the display to fall back on the ListBox's Template,
though now my ItemTemplate is used:</TextBlock>
<control:RotatingFlipView x:Name="Broken2"
ItemsSource="{StaticResource MyColors}">
<control:RotatingFlipView.ItemTemplate>
<DataTemplate>
<Rectangle Height="100" Width="100" Fill="{Binding}"/>
</DataTemplate>
</control:RotatingFlipView.ItemTemplate>
</control:RotatingFlipView>
</StackPanel>
RotatingFlipView.cs
public class RotatingFlipView : ListBox
{
public RotatingFlipView()
{
DefaultStyleKey = typeof(RotatingFlipView);
}
}
generic.xaml
<Style TargetType="local:RotatingFlipView">
<Setter Property="SelectionMode" Value="Single"/>
<Setter Property="SelectedIndex" Value="0"/>
</Style>
Output:
I have now figured it out. Here is how I've done it:
Mainpage.xaml
<UserControl.Resources>
<local:StringCollection x:Key="MyColors">
<sys:String>Yellow</sys:String>
<sys:String>Purple</sys:String>
</local:StringCollection>
</UserControl.Resources>
<StackPanel Background="White">
<control:RotatingFlipView>
<Rectangle Height="100" Width="100" Fill="Red"/>
<Rectangle Height="100" Width="100" Fill="Green"/>
<Rectangle Height="100" Width="100" Fill="Blue"/>
</control:RotatingFlipView>
<control:RotatingFlipView ItemsSource="{StaticResource MyColors}">
<control:RotatingFlipView.ItemTemplate>
<DataTemplate>
<Rectangle Height="100" Width="100" Fill="{Binding}"/>
</DataTemplate>
</control:RotatingFlipView.ItemTemplate>
</control:RotatingFlipView>
<StackPanel/>
RotatingFlipView.cs
public class RotatingFlipView : ListBox
{
public RotatingFlipView()
{
DefaultStyleKey = typeof(RotatingFlipView);
}
}
generic.xaml
<Style TargetType="local:RotatingFlipView">
<Setter Property="SelectionMode" Value="Single"/>
<Setter Property="SelectedIndex" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:RotatingFlipView">
<ContentPresenter
Content="{TemplateBinding SelectedItem}"
ContentTemplate="{TemplateBinding ItemTemplate}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Include the templated Control into template?

I want to template a Control and include the Control itself into the template, not only the control's content.
For example, I have a button:
<Grid x:Name="LayoutRoot" Background="White">
<Button Name="hello" Content="123" Width="100" Height="100" >
</Button>
</Grid>
I want to make a broader to surround this button, so it will look like this:
<Grid x:Name="LayoutRoot" Background="White" Width="120" Height="120">
<Rectangle Fill="AliceBlue"/>
<Button Name="hello" Content="123" Width="100" Height="100" >
</Button>
</Grid>
But I want to make this more genric, not only for button, but for some other control.
i.e Image, TreeViewItem etc.
So I created a template:
<UserControl.Resources>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Width="120" Height="120">
<Rectangle Fill="AliceBlue"/>
<ContentPresenter Content="{TemplateBinding Property=ContentControl.Content}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<Button Name="hello" Content="123" Width="100" Height="100" >
</Button>
</Grid>
Now the ContentPresenter only display the content of the Button, but not include the button itself, how can I include the templated control itself too?

Categories