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?
Related
In my MainWindow I have defined a region, that I am injecting my UserControls into (using Prism, but it doesn't matter). My control should be resizeable (it works perfectly) and moveable. To drag and move my user control I am using Blend's MouseDragElementBehavior. Problem is, that although my control moves, when I resize MainWindow it gets cut :
When I am not moving my control everything works, as expected, when I resize MainWindow scrollBar shows up:
But when I move my user control to the bottom of the MainWindow, the ScrollBar is not showing up like it does't know, that my control has been moved:
Important: The ScrollBar is showing up in both scenarios at exact same time, though when I move my user control down it should appear much more sonner, when I reach the bounds of the user control. On the picture below you can see the moment when the ScrollBar is showing up after I draged my control down. It appeared too late, control gets cut.
It's hard to explain, let me know if you understood me correctly.
My code:
<Window x:Class="ViewInjection.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
Title="MainWindow">
<ScrollViewer HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*" ScrollViewer.CanContentScroll="True" ScrollViewer.IsDeferredScrollingEnabled="True"/>
</Grid.RowDefinitions>
<Button Grid.Row="0" Click="Button_Click">Add View</Button>
<ItemsControl Grid.Row="1" prism:RegionManager.RegionName="ContentRegion" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
</ScrollViewer>
</Window>
UserControl:
<UserControl
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:ViewInjection.Views"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" x:Class="ViewInjection.Views.ViewA"
mc:Ignorable="d">
<Border x:Name="Border" HorizontalAlignment="Center" VerticalAlignment="Center" BorderBrush="#FF626161" BorderThickness="2" CornerRadius="3" MinHeight="200" MinWidth="200">
<i:Interaction.Behaviors>
<ei:MouseDragElementBehavior ConstrainToParentBounds="true"/>
</i:Interaction.Behaviors>
<DockPanel x:Name="sizableContent" Background="LightGray" Focusable="False" LastChildFill="True" MinHeight="300" MinWidth="300">
<DockPanel DockPanel.Dock="Bottom" >
<!--Make user control resizeable-->
<Thumb DockPanel.Dock="Right" VerticalAlignment="Bottom" Margin="0,0,1,1"
DragDelta="OnResizeThumbDragDelta"
DragStarted="OnResizeThumbDragStarted"
DragCompleted="OnResizeThumbDragCompleted">
<Thumb.Style>
<Style TargetType="{x:Type Thumb}">
<Style.Setters>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid x:Name="resizeVisual" DockPanel.Dock="Right" VerticalAlignment="Bottom" >
<Line X1="6" Y1="18" X2="18" Y2="6" Stroke="DarkGray" StrokeThickness="1.5"/>
<Line X1="10" Y1="18" X2="18" Y2="10" Stroke="DarkGray" StrokeThickness="1.5"/>
<Line X1="14" Y1="18" X2="18" Y2="14" Stroke="DarkGray" StrokeThickness="1.5"/>
<Grid.Style>
<Style TargetType="{x:Type Grid}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="SizeNWSE"/>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
</Thumb.Style>
</Thumb>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
<Button Margin="12" Width="75" TabIndex="1" Content="Ok"/>
</StackPanel>
</DockPanel>
<StackPanel HorizontalAlignment="Center" Margin="16,16,16,4">
<TextBlock Text="My UserControl"/>
</StackPanel>
</DockPanel>
</Border>
</UserControl>
P.S.
I am using items control to have multiple controls within that region. I am using Grid as a template, because I want controls to overlap each other.
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
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>
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>
How do I create a circle shape button but with the color affected by binding.
I have already something like this:
<Button Command="{Binding ShowDetails}" Background="{Binding Color} />
and the color that will be received will be of this format, for example: Colors.LightGray
Can anyone help me?
If you google for "circular button template silverlight" you will find lots of blog posts that describe this process. Including previous StackOverflow questions:
Silverlight: Creating a round button template
The basic steps are
Create a new ControlTemplate for your buttons that renders a circle, using an Ellipse for example.
If you want your Buttton.Background to set the Fill color, then use a TemplateBinding for the Ellipse.Fill property.
For example:
<Button Content="MyButton">
<Button.Template>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Fill="{TemplateBinding Background}"/>
<ContentPresenter Content="{TemplateBinding Content}"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
You will have to write the control template for the button like this
<Button Content="MyButton">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Ellipse Fill="{TemplateBinding Background}"/>
<ContentPresenter x:Name="content" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
With the color binding :
<UserControl.Resources>
<Color x:Key="MyColor">LightGray</Color>
<Style x:Key="RoundButton" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Width="40" Height="40" Stroke="#FF000000" StrokeThickness="1" Canvas.Left="141" Canvas.Top="61">
<Ellipse.Fill>
<SolidColorBrush Color="{StaticResource MyColor}" />
</Ellipse.Fill>
</Ellipse>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<Button Style="{StaticResource RoundButton}" />
</Grid>
Enjoy ;)