Mouseover-trigger on Slider Template - c#

I'm changing the Standard WPF Slider's template. And I want it where you move your mouse over the area the slider occupies and the thumb starts an animation to change its size, even if the cursor isn't directly on top of the thumb.
But I don't know how to bind to a parent like that.
I'll try to post what I got without making it look nasty. Here's what I got that's relevant (I think. If you need more, tell me)
<ControlTemplate x:Key="SliderHorizontal" TargetType="{x:Type Slider}" x:Name="SliderHorizontal">
<Track x:Name="PART_Track" Grid.Row="1">
<Track.DecreaseRepeatButton>
<RepeatButton Command="{x:Static Slider.DecreaseLarge}" Style="{StaticResource LeftRepeatButtonTransparent}">
</RepeatButton>
</Track.DecreaseRepeatButton>
<Track.IncreaseRepeatButton>
<RepeatButton Command="{x:Static Slider.IncreaseLarge}" Style="{StaticResource RightRepeatButtonTransparent}"/>
</Track.IncreaseRepeatButton>
<Track.Thumb>
<Thumb x:Name="Thumb" Focusable="False" Height="20" OverridesDefaultStyle="True" Template="{StaticResource SliderThumbHorizontalDefault}" VerticalAlignment="Center" Width="Auto" Margin="0,0,-5.5,0">
</Thumb>
</Track.Thumb>
</Track>
</Grid>
</Border>
<ControlTemplate.Triggers>
triggers galore
</ControlTemplate.Triggers>
</ControlTemplate>
And here is the template for the thumb itself. It's the ellipse grip I want to change the size of.
<ControlTemplate x:Key="SliderThumbHorizontalDefault" TargetType="{x:Type Thumb}">
<Ellipse x:Name="grip" Fill="White" Height="15" Width="15" Effect="{StaticResource z-depth1}">
</Ellipse>
<ControlTemplate.Triggers>
more triggers
</ControlTemplate.Triggers>
</ControlTemplate>
How would I go about doing this binding?
Any help would be appreciated!!

Within the RenderTransform block I would add a scaleTransform
<Style x:Key="HorizontalSliderThumbStyle" TargetType="{x:Type Thumb}">
.....
.....
<ControlTemplate TargetType="{x:Type Thumb}">
<Canvas x:Name="canvas" SnapsToDevicePixels="true">
<Canvas.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1"/>
<TranslateTransform X="5.5" Y="11"/>
</TransformGroup>
</Canvas.RenderTransform>
Then within the control template's triggers I would add the scaling up of the canvas.
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Trigger.EnterActions>
<BeginStoryboard Name="EnlargeThumb">
<Storyboard TargetName="canvas"
TargetProperty="RenderTransform.Children[1].ScaleX" >
<DoubleAnimation To="2" Duration="0:0:0" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<StopStoryboard BeginStoryboardName="EnlargeThumb" />
</Trigger.ExitActions>
</Trigger>
Note the style and what not that I got is from the template extracted via visual studio.

Related

Is there a way to use IsMouseOver in a resource dictionary

When I use the below block of code in a Window or control it works (I can see the button animation and the size of the button changes when I hover over it), but it does not work when I use it in the resource dictionary. I am creating a Prism app with mah apps window.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:b="http://schemas.microsoft.com/expression/2010/interactivity"
>
<!--// Merge Dic here //-->
<ContentControl x:Key="OperatorUIPreview"
Content="{StaticResource splashStyle}"/>
<ContentControl x:Key="OperatorUI.Home"
Background="Purple">
<Grid >
<Border
Background="#323345"
CornerRadius="10,10,0,0"
Margin="0,85,0,0">
<Grid >
<Button
x:Name="home1"
Background="Blue"
Style="{StaticResource DockBtnStyle}">
<Popup Width="70"
HorizontalOffset="-12"
PlacementTarget="{Binding ElementName=home1}"
IsOpen="{Binding ElementName=home1, Path=IsMouseOver, Mode=OneWay}"
Style="{StaticResource PopupStyle}">
<Grid>
<Border Style="{StaticResource border}">
<TextBlock Text="Home"
Style="{StaticResource PopupText}" />
</Border>
<Path Style="{StaticResource ArrowPath}"/>
</Grid>
</Popup>
</Button>
</Grid>
</Border>
</Grid>
</ContentControl>
</ResourceDictionary>
Style:
<Style x:Key="DockBtnStyle"
TargetType="Button">
<Setter Property="Height"
Value="50" />
<Setter Property="Width"
Value="50" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="border"
BorderThickness="0"
Background="{TemplateBinding Background}" />
</ControlTemplate>
</Setter.Value>
</Setter>
<!--// Button Animation //-->
<Style.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Button.Width)"
To="65"
Duration="0:0:0.3" />
<DoubleAnimation Storyboard.TargetProperty="(Button.Height)"
To="65"
Duration="0:0:0.3" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Button.Width)"
To="50"
Duration="0:0:0.3" />
<DoubleAnimation Storyboard.TargetProperty="(Button.Height)"
To="50"
Duration="0:0:0.3" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>

How to overlay items in StackPanel or ListView?

I am making a card game and I want to display cards in player's hand half-covered be each other. How can I do that using ListView or StackPanel? Here is an example how I would like to display player hand.
<Grid Background="Green" >
<Image x:Name="One" Width="100" Height="100" Margin="10,10,250,210"/>
<Image x:Name="Two" Width="100" Height="100" Margin="10,10,210,210"/>
</Grid>
UPDATE
I set margins for ListView's ItemContainerStyle and it worked, but I have another problem. Width of ListView items doesn't fit the image and there is some spacing. How do I remove that. See image below the XAML code.
<ListView Grid.Row="0" Grid.Column="0">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Margin" Value="0, 0, -80, 0"></Setter>
<Setter Property="Height" Value="100"></Setter>
<Setter Property="Width" Value="100"></Setter>
</Style>
</ListView.ItemContainerStyle>
<Image x:Name="One" MaxWidth="100" Height="100" />
<Image x:Name="Two" MaxWidth="100" Height="100" />
</ListView>
I would use Canvas in the list, and draw your card to the canvas, because things drawn in a canvas are not clipped, and instead managed through the canvas ZIndex etc.
Size the canvas based on your desired spacing, and oversize the contents. I'd also recommend binding to Items-source when using listboxes and using templates.
BTW I'm defining my cards using solidColorBrushes so I can just draw rectangles, replace this with your image source. I've defined my source in the resources, but in reality it would be bound to an ObservableCollection (Say, PlayersCurrentHand or something):
<UserControl.Resources>
<x:Array Type="{x:Type SolidColorBrush}" x:Key="Cards">
<SolidColorBrush Color="Blue"/>
<SolidColorBrush Color="Red"/>
<SolidColorBrush Color="White"/>
<SolidColorBrush Color="White"/>
<SolidColorBrush Color="White"/>
<SolidColorBrush Color="White"/>
</x:Array>
</UserControl.Resources>
Now, I presume you are using ListBox because you want to support selection? If so, the way WPF highlights list box items will mess up with this overlap, so we will need to replace it. If you don't want selection, just use an itemsControl and you can skip all the selection stuff.
Here's our basic listbox:
<ListView ItemsSource="{StaticResource Cards}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="112,98,-325,-25" Width="513" Height="227">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" IsItemsHost="True" VerticalAlignment="Top"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="1">
<Rectangle Fill="{Binding}" Width="60" Height="100"/>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Which gives us this:
Now, we want to have all the list items to be drawn in a canvas, so let's define our ItemContainerStyle:
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<StackPanel>
<Canvas Width="15" Height="100">
<ContentPresenter />
</Canvas>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
See how we've set the canvas Width to 15? That defines the spacing of our cards. All the canvases are stacked at intervals of 15. However, the Rectangles we are drawing in our DateTemplate is Width 60, so these spill off to the right.
We've overridden the messy standard selection and highlighting styles. But no we don't know what's highlighted and selected, so let's add some functionality back in. We can also add things like shadows etc:
<ControlTemplate TargetType="{x:Type ListViewItem}">
<StackPanel>
<Canvas Width="15" Height="100">
<Rectangle x:Name="Highlight" Width="60" Height="5" Canvas.Top="105"/>
<Rectangle Fill="#50000000" Width="60" Height="100" Margin="5,0,-5,0"/>
<ContentPresenter />
</Canvas>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Highlight" Property="Fill" Value="Yellow"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Panel.ZIndex" Value="99"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
So now we have this:
Note, the gif didn't render the selection exactly right. The width issue is going to be tricky to fix without some code behind I think. One option is to make an IValueConverter that calculates width given the List of cards, and binding it to the Listview's Width property.
Edit
Found a way to get around the size issue! Padding! Of course. However, I found the scroll viewer clips even the canvas it contains (which makes sense if you think about it) but leaves all our effort hidden:
So you have to overwrite the scroll viewer functionality by setting the ControlTemplate manually:
<ListBox.Template>
<ControlTemplate>
<Border Padding="5,25,55,15" BorderBrush="Gray" BorderThickness="1">
<ItemsPresenter />
</Border>
</ControlTemplate>
</ListBox.Template>
So now the padding accounts for the last card sticking out an extra 50.
Total code, with some more visual tweaks:
<ListView ItemsSource="{StaticResource Cards}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="20" BorderBrush="Black">
<ListBox.Template>
<ControlTemplate>
<Border Padding="5,25,55,15" BorderBrush="Gray" BorderThickness="1">
<ItemsPresenter />
</Border>
</ControlTemplate>
</ListBox.Template>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" IsItemsHost="True" ClipToBounds="False" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<StackPanel>
<Canvas Width="15" Height="100">
<Rectangle x:Name="Highlight" Width="60" Height="5" Canvas.Top="105"/>
<ContentPresenter x:Name="CardPresenter"/>
</Canvas>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Panel.ZIndex" Value="99"/>
<Setter TargetName="CardPresenter" Property="Canvas.Top" Value="-5"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Highlight" Property="Fill" Value="Yellow"/>
<Setter TargetName="CardPresenter" Property="Canvas.Top" Value="-20"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Border Background="#60000000" BorderThickness="0" CornerRadius="5" Height="100" Margin="5,0,-5,0"/>
<Border BorderBrush="Black" BorderThickness="1" CornerRadius="5" Background="{Binding}" Width="60" Height="100"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
It's pretty flexible, it was easy to add the "sticking out" functionality. Animations would be the next big step.
Edit 2
I'm just playing now. I'm not sure I like the "jump to the front" functionality, would be better if they just peeked out. Also, fanning them out (using a multi-binding):
Using the following template:
<ControlTemplate TargetType="{x:Type ListViewItem}">
<StackPanel>
<Canvas Width="15" Height="100">
<Rectangle x:Name="Highlight" Width="60" Height="5" Canvas.Top="105"/>
<ContentPresenter x:Name="CardPresenter">
<ContentPresenter.RenderTransform>
<TransformGroup>
<TranslateTransform x:Name="TranslateTransformHighlight"/>
<RotateTransform x:Name="RotateTransformHighlight" CenterY="100"/>
<TranslateTransform x:Name="TranslateTransformSelect"/>
</TransformGroup>
</ContentPresenter.RenderTransform>
</ContentPresenter>
</Canvas>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True" >
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="TranslateTransformHighlight" Duration="0:0:0.200" To="-5" Storyboard.TargetProperty="Y" />
<DoubleAnimation Storyboard.TargetName="RotateTransformHighlight" Duration="0:0:0.200" To="-5" Storyboard.TargetProperty="Angle" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="TranslateTransformHighlight" Duration="0:0:0.200" To="0" Storyboard.TargetProperty="Y" />
<DoubleAnimation Storyboard.TargetName="RotateTransformHighlight" Duration="0:0:0.200" To="0" Storyboard.TargetProperty="Angle" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Highlight" Property="Fill" Value="Yellow"/>
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="TranslateTransformSelect" Duration="0:0:0.200" To="-15" Storyboard.TargetProperty="Y" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="TranslateTransformSelect" Duration="0:0:0.200" To="0" Storyboard.TargetProperty="Y" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>

How to use image in WPF progressbar?

I have a picture, I want to use it in WPF as a progressbar.
Please look at the image to understand this.
The code below, repeated the image.
The moving progress-box above the progressbar.
I have tried this
<ControlTemplate
x:Key="ImageProgressBarTemplate"
TargetType="ProgressBar">
<ControlTemplate.Triggers>
<EventTrigger
RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard
x:Name="str">
<RectAnimation
x:Name="quatanim"
Storyboard.TargetName="imgbrush"
Storyboard.TargetProperty="(ImageBrush.Viewport)"
From="0,0,36,36"
To="36,0,36,36"
Duration="0:0:5"
AutoReverse="False"
RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
<!-- Custom progress bar goes here -->
<Border
Name="PART_Track"
Width="{TemplateBinding Width}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
Height="{TemplateBinding Height}"
CornerRadius="0"
Padding="1.5">
<Grid>
<!-- Rounded mask (stretches to fill Grid) -->
<Border
Name="mask"
Background="#EEEEEE"
CornerRadius="0" />
<!-- Any content -->
<Rectangle
Name="PART_Indicator"
HorizontalAlignment="Left"
Height="{TemplateBinding Height}">
<Rectangle.OpacityMask>
<VisualBrush
Visual="{Binding ElementName=mask}" />
</Rectangle.OpacityMask>
<Rectangle.Fill>
<ImageBrush
x:Name="imgbrush"
ImageSource="/myproject;component/Assets/myimage.png"
AlignmentX="Left"
Stretch="Fill"
TileMode="Tile"
AlignmentY="Top"
ViewportUnits="Absolute"
Viewport="0,0,36,36"
ViewboxUnits="RelativeToBoundingBox"
Viewbox="0,0,1,1">
</ImageBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Border>
<ProgressBar Template="{StaticResource ImageProgressBarTemplate}"/>
The all that I need is a detailed tutorial of how to use image in wpf progressbar for this kind of images.
You have to design your own template of progressbar.
<ControlTemplate TargetType="ProgressBar">
<Canvas>
<ProgressBar x:Name="pgbar" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"
Value="{TemplateBinding Value}"
Minimum="{TemplateBinding Minimum}"
Maximum="{TemplateBinding Maximum}"/>
<Image Source="image.PNG" Canvas.Left="{TemplateBinding Value}">
<Image.RenderTransform>
<!-- width / 2 and height /2-->
<TranslateTransform X="-56" Y="-25"/>
</Image.RenderTransform>
</Image>
</Canvas>
</ControlTemplate>
An improvement for the answer of Klaus Fischer:
Here is the ProgressBar:
<ProgressBar Value="{Binding ProgressbarValue}" Template="{StaticResource Progressbar2}" />
And here is the template (See post of Klaus Fischer):
<ControlTemplate x:Key="Progressbar2" TargetType="ProgressBar">
<Canvas >
<ProgressBar x:Name="pgbar" Visibility="Hidden" Width="{Binding ElementName=StatusGrid,Path=ActualWidth}" Background="Transparent" Value="{TemplateBinding Value}" />
<Image Source="Resources/Images/running.png" Height="42px" Canvas.Left="{TemplateBinding Value, Converter={StaticResource WidthConverter}, ConverterParameter={x:Reference pgbar}}" />
</Canvas>
</ControlTemplate>
As you can see, there is a converter in the
Canvas.Left
property.
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var bar = ((System.Windows.Controls.ProgressBar) parameter);
var percentPixe = bar.ActualWidth/100;
return percentPixe*(double) value-42;
}
The expression
value-42
handles the size of the image, otherwise the image would be in front of the real ProgressBar.
This should do the job.

How to create circle button with image background and CLICKING feel IN Silverlight

Right now i can change the look of the button to an ellipse with a background image.
However, when i click on it, i don't feel the CLICKING EFFECT of the normal buttons in Silverlight
Can anyone help me how to get that effect?
this is my XAML style for the round button
<style x:Key="roundButton" TargetType="Button">
<Setter Properties="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Ellipse width="100" height="100">
<Ellipse.Fill>
<ImageBrush ImageSource="./icon.png">
</Ellipse.Fill>
</Ellipse>
</ControlTemplate>
</Setter.Value>
</Setter>
</style>
after searching around i know that i should use the VisualStateManager in Systems.Window. This is how my XAML looks now but i still can't get the CLICKING feeling like normal buttons
<Style x:Key="roundButton" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Width="100" Height="100">
<Ellipse.Fill>
<ImageBrush ImageSource="./icon.png" />
</Ellipse.Fill>
</Ellipse>
<vsm:VisualStateManager.VisualStateGroups>
<vsm:VisualStateGroup x:Name="CommonStates">
<vsm:VisualState x:Name="MouseOver"/>
<vsm:VisualState x:Name="Normal"/>
<vsm:VisualState x:Name="Pressed"/>
<vsm:VisualState x:Name="Disabled"/>
</vsm:VisualStateGroup>
<vsm:VisualStateGroup x:Name="FocusStates">
<vsm:VisualState x:Name="Unfocused"/>
<vsm:VisualState x:Name="Focused"/>
</vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You need to set the triggers for your button for the respective state.
<style x:Key="roundButton" TargetType="Button">
<Setter Properties="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Ellipse width="100" height="100">
<Ellipse.Fill>
<ImageBrush ImageSource="./icon.png"/>
</Ellipse.Fill>
</Ellipse>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!-- mouse over look and feel here -->
</Trigger>
<Trigger Property="IsPressed" Value="True">
<!-- clicked look and feel here -->
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</style>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
<Ellipse.Fill>
<RadialGradientBrush GradientOrigin=".2,.2">
<GradientStop Offset="0.2" Color="White" />
<GradientStop Offset="1" Color="Blue" />
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<ContentPresenter Content="{TemplateBinding Content}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Far more simple way is to use Blend. Drag and Drop Ellipse, convert it into control(button). Go to StatesTab adjust the states accordingly. Normally, on pressed state, apply scale trasform to reduce the button size and use translate transform to move the button (appro 2px amount) towards bottom/right would do the trick.
HTH

iPhone like red badge notification in a WPF project?

I have a C# WPF project which generates daily and weekly reports automatically. I want to inform the user when new reports are available, so I thought of a badge like on the iPhone where the number of new messages appears on a little red circle:
I thought of three images: Two images with semi circles on the left and right if the number to display is small. And a third image for the middle for the case that the number is large (123) and wouldn't fit in a circle.
I want a glossy effect, so I've thought of pictures. Does anyone have a good idea how to do this without pictures but programmatically?
Use a Border element and place your text within it. You can set the CornerRadius property for the Border appropriately so that it looks like a circle (or a rounded-rectangle shape, in case the number is bigger).
Here's a first cut, which exploits the fact that CornerRadius will get clamped to half the height or width in Y and X respectively:
<Border Background="Red" CornerRadius="999" Padding="4">
<TextBlock Foreground="White" FontWeight="Bold" FontSize="12">125</TextBlock>
</Border>
I recently had the same requirement, and quickly knocked this UserControl together.
It uses a short animation to draw the user's attention to the badge.
Take a look at "Big Nick's" blog to see some elegant code for applying this UserControl to another UIElement as an Adorner (exactly what a 'badge' is!):
http://blog.bignickolson.com/2009/10/15/overlaying-controls-in-wpf-with-adorners/
(Thanks Nick!)
<UserControl x:Class="BadgeControl"
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"
mc:Ignorable="d"
Opacity="0.8"
ClipToBounds="False"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<Style TargetType="Label" x:Key="BadgeLabel">
<Setter Property="Foreground" Value="White" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Height" Value="22" />
<Setter Property="MinWidth" Value="22" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Label">
<Border Name="badgeOuterBorder" CornerRadius="10" BorderBrush="White" BorderThickness="2" Background="#C80103">
<Border.RenderTransform>
<!--
The TranslateTransform moves the badge so that when used as an Adorner, it bleeds over the upper left
edge of the adorned control.
The ScaleTransform ensures the badge is initially invisible on load ,
but gives the storyboard the ability to 'animate' it into visibility (by manipulating the ScaleTransform).
-->
<TransformGroup>
<TranslateTransform X="-8" Y="-8"/>
<ScaleTransform ScaleX="0" ScaleY="0" />
</TransformGroup>
</Border.RenderTransform>
<Border.BitmapEffect>
<!-- Give some depth to the badge with a drop-shadow -->
<DropShadowBitmapEffect Color="Black" Direction="270" ShadowDepth="3" Softness="0.2" Opacity="1"/>
</Border.BitmapEffect>
<Border CornerRadius="8" Padding="5 0 5 0">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1" Opacity="0.8">
<GradientStop Color="White" Offset="0" />
<GradientStop Color="Transparent" Offset="0.6" />
</LinearGradientBrush>
</Border.Background>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Content="{TemplateBinding Content}"></ContentPresenter>
</Border>
</Border>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<!--
The following storyboard animates the ScaleTransform in both the X and Y planes, so that the
badge appears to 'pop' into visibility.
The 1 second delay ensures that the parent control is fully visible before the animation begins,
otherwise, the animation may actually run before the form has rendered to the screen.
-->
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="badgeOuterBorder"
Storyboard.TargetProperty="(Border.RenderTransform).(TransformGroup.Children)[1].(ScaleTransform.ScaleX)"
From="0"
To="0.75"
BeginTime="0:0:1"
Duration="0:0:0.5">
<DoubleAnimation.EasingFunction>
<BackEase Amplitude='1' EasingMode='EaseOut' />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation
Storyboard.TargetName="badgeOuterBorder"
Storyboard.TargetProperty="(Border.RenderTransform).(TransformGroup.Children)[1].(ScaleTransform.ScaleY)"
From="0"
To="0.75"
BeginTime="0:0:1"
Duration="0:0:0.5">
<DoubleAnimation.EasingFunction>
<BackEase Amplitude='1' EasingMode='EaseOut' />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid HorizontalAlignment="Left" VerticalAlignment="Top" ClipToBounds="False">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center" Name="d" ClipToBounds="False">
<Label Style="{StaticResource BadgeLabel}" Content="Badge Text" ToolTip="Badge Tooltip" ClipToBounds="False" />
</Grid>
</Grid>
</UserControl>
This is based on Chris1 answer, but this will stretch correctly when the text inside the badge is longer than one digit, I've also set the font to make it more consistent across Windows versions, changed the sizing a bit to compensate and added an outline around the badge.
I've also replaced DropShadowEffect with a Rectangle, this is because I can't use DropShadowEffect in my specific application, DropShadowEffect looks better but my Rectangle shadow is good enough, you can delete the shadow rectangle and use DropShadowEffect if you like.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<Style TargetType="Label" x:Key="CircularLabel">
<Setter Property="Foreground" Value="White" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="FontSize" Value="13" />
<Setter Property="FontFamily" Value="Arial" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Label">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Rectangle Margin="0 3 0 -3" Fill="LightGray"
RadiusX="11" RadiusY="11" Opacity="0.8"/>
<Border CornerRadius="11"
BorderBrush="DarkGray"
BorderThickness="1">
<Border
HorizontalAlignment="Center"
VerticalAlignment="Center" CornerRadius="10"
Background="#FFC90000"
BorderBrush="White"
BorderThickness="2">
<Grid>
<ContentPresenter
HorizontalAlignment="Center" VerticalAlignment="Center"
Content="{TemplateBinding Content}" Margin="5 1 6 1"/>
<Rectangle x:Name="TopShine" RadiusX="9" RadiusY="9"
VerticalAlignment="Stretch">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1" Opacity="0.6">
<GradientStop Color="White" Offset="0.2" />
<GradientStop Color="Transparent" Offset="0.7" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Border>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<Grid>
<UniformGrid>
<Label Style="{StaticResource CircularLabel}">4</Label>
<Label Style="{StaticResource CircularLabel}">100000</Label>
<Label Style="{StaticResource CircularLabel}">CLICK HERE</Label>
</UniformGrid>
</Grid>
</Page>
There are many WPF tutorials out there for glossy buttons. Basically, create a normal button and use the combination of effects and gradients to change the button control template to look like an iPhone button. This is a sample but you can do much more: http://craig.palenshus.com/silverlight/silverlight-and-the-content-presenter-in-an-iphone-like-button/
Here is my go at it, it is not perfect but it looks good enough.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<DropShadowEffect x:Key="ShadowEffect" Direction="270" BlurRadius="5" ShadowDepth="3"/>
<Style TargetType="Label" x:Key="CircularLabel">
<Setter Property="Foreground" Value="White" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Label">
<Grid>
<Rectangle HorizontalAlignment="Center" VerticalAlignment="Center" Width="20" Height="20" Fill="#FFC90000" RadiusX="10" RadiusY="10" Stroke="White" StrokeThickness="2" Effect="{StaticResource ShadowEffect}" />
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Content="{TemplateBinding Content}"></ContentPresenter>
<Rectangle x:Name="TopShine" RadiusX="10" RadiusY="10" Width="20" Height="20" StrokeThickness="2">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1" Opacity="0.8">
<GradientStop Color="White" Offset="0" />
<GradientStop Color="Transparent" Offset="0.6" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<Grid>
<Label Style="{StaticResource CircularLabel}">1</Label>
</Grid>
</Page>

Categories