What is the best way to slide a panel in WPF? - wpf

I have a fairly simple UserControl that I have made (pardon my Xaml I am just learning WPF) and I want to slide the off the screen. To do so I am animating a translate transform (I also tried making the Panel the child of a canvas and animating the X position with the same results), but the panel moves very jerkily, even on a fairly fast new computer. What is the best way to slide in and out (preferably with KeySplines so that it moves with inertia) without getting the jerkyness. I only have 8 buttons on the panel, so I didn't think it would be too much of a problem.
Here is the Xaml I am using, it runs fine in Kaxaml, but it is very jerky and slow (as well as being jerkly and slow when run compiled in a WPF app).
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="1002" Height="578">
<UserControl.Resources>
<Style TargetType="Button">
<Setter Property="Control.Padding" Value="4"/>
<Setter Property="Control.Margin" Value="10"/>
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Name="backgroundGrid" Width="210" Height="210" Background="#00FFFFFF">
<Grid.BitmapEffect>
<BitmapEffectGroup>
<DropShadowBitmapEffect x:Name="buttonDropShadow" ShadowDepth="2"/>
<OuterGlowBitmapEffect x:Name="buttonGlow" GlowColor="#A0FEDF00" GlowSize="0"/>
</BitmapEffectGroup>
</Grid.BitmapEffect>
<Border x:Name="background" Margin="1,1,1,1" CornerRadius="15">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0" Color="#FF0062B6"/>
<GradientStop Offset="1" Color="#FF0089FE"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
</Border>
<Border Margin="1,1,1,0" BorderBrush="#FF000000" BorderThickness="1.5" CornerRadius="15"/>
<ContentPresenter HorizontalAlignment="Center" Margin="{TemplateBinding Control.Padding}"
VerticalAlignment="Center" Content="{TemplateBinding ContentControl.Content}"
ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Canvas>
<Grid x:Name="Panel1" Height="578" Canvas.Left="0" Canvas.Top="0">
<Grid.RenderTransform>
<TransformGroup>
<TranslateTransform x:Name="panelTranslate" X="0" Y="0"/>
</TransformGroup>
</Grid.RenderTransform>
<Grid.RowDefinitions>
<RowDefinition Height="287"/>
<RowDefinition Height="287"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="Panel1Col1"/>
<ColumnDefinition x:Name="Panel1Col2"/>
<ColumnDefinition x:Name="Panel1Col3"/>
<ColumnDefinition x:Name="Panel1Col4"/>
<!-- Set width to 0 to hide a column-->
</Grid.ColumnDefinitions>
<Button x:Name="Panel1Product1" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click" SourceName="Panel1Product1">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation BeginTime="00:00:00.6" Duration="0:0:3" From="0" Storyboard.TargetName="panelTranslate" Storyboard.TargetProperty="X" To="-1000"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Button.Triggers>
</Button>
<Button x:Name="Panel1Product2" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Button x:Name="Panel1Product3" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Button x:Name="Panel1Product4" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Button x:Name="Panel1Product5" Grid.Column="2" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Button x:Name="Panel1Product6" Grid.Column="2" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Button x:Name="Panel1Product7" Grid.Column="3" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Button x:Name="Panel1Product8" Grid.Column="3" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Canvas>
</UserControl>

It looks like the best solution so far, is to use a Visual Brush and move two static images when sliding in and out the panels. Something similar to this is described in this blog post:
Using animated navigation pages in a WPF application (switched to web archive, but this is from 2008 so no promises if it is still the best technique).

I've found WPF performance of animations to improve significantly when not using BitmapEffects. Try disabling them in your example. I replaced my drop shadows with semi-transparent solid regions with gradient fills and performance improved.
I've also heard that some bitmap effects have increased performance in newer versions (maybe 3.5 SP1?) as more of the rendering has been pushed to the hardware.

If you work with WPF animations long enough, you'll figure out that large-area controls do, in fact, move in a what you call 'jerky' manner. I've had this problem even with tiny buttons that needed to move horizontally on the screen, and I have certainly given up on moving anything large (e.g., a window).

Related

Viewbox and Canvas

this is my first intervention here. I'm sorry in advance for my poor english and i wish i will be clear.
I'm Making a custom control. (i'm a beginner in wpf) his goal is depending of a Property "Type Control". It could be a simpe textblock displaying data (and change background color depending on level property), it could be a marquee text or could be a picture.The goal here is to make a dynamic control. I explain this but my real trouble his the marquee part.
This is my XAML code :
<ControlTemplate TargetType="{x:Type local:ControlPerso}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" x:Name="PART_BORDER" VerticalAlignment="Stretch" CornerRadius="10" Height="Auto">
<Viewbox Margin="2" StretchDirection="DownOnly" x:Name="PART_VB" Stretch="Fill">
<Grid x:Name="PART_GRID" ShowGridLines="false" VerticalAlignment="Center" Height="Auto" >
<Grid.RowDefinitions>
<RowDefinition x:Name="PART_ROWLABEL"></RowDefinition>
<RowDefinition x:Name="PART_ROWSCROLL"></RowDefinition>
<RowDefinition x:Name="PART_ROWIMAGE"></RowDefinition>
</Grid.RowDefinitions>
<Grid Grid.Row="0" x:Name="RowLabel" VerticalAlignment="Center">
<TextBlock x:Name="PART_LABEL" Text="{Binding MyText, RelativeSource='{RelativeSource Mode=TemplatedParent}', UpdateSourceTrigger=PropertyChanged}" Background="Transparent"
FontFamily="Verdana" FontSize="{Binding FontSize, RelativeSource='{RelativeSource Mode=TemplatedParent}'}" FontWeight="ExtraBold" HorizontalAlignment="Center">
<TextBlock.BitmapEffect>
<DropShadowBitmapEffect Color="Black" Direction="320" ShadowDepth="2" Opacity=".9" Softness="0.3" />
</TextBlock.BitmapEffect>
</TextBlock>
</Grid>
<Grid Grid.Row="1" x:Name="RowScroll" VerticalAlignment="Center">
<Canvas x:Name="PART_ContentControl" ClipToBounds="True"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Height="{Binding ActualHeight, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Width="{Binding ActualWidth, RelativeSource={RelativeSource Mode=TemplatedParent}}" >
<Canvas.Triggers>
<EventTrigger RoutedEvent="Canvas.Loaded">
<BeginStoryboard>
<Storyboard x:Name="ContentTickerStoryboard" Storyboard.TargetProperty="(Canvas.Left)">
<DoubleAnimation Storyboard.TargetName="PART_Content" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Canvas.Triggers>
<ContentPresenter x:Name="PART_Content"
HorizontalAlignment="{TemplateBinding ContentControl.HorizontalAlignment}"
VerticalAlignment="{TemplateBinding ContentControl.VerticalAlignment}"
Content="{Binding MyText, RelativeSource={RelativeSource Mode=TemplatedParent}, UpdateSourceTrigger=PropertyChanged}"
ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" TextBlock.FontSize="{Binding FontSize, RelativeSource='{RelativeSource Mode=TemplatedParent}'}">
<ContentPresenter.BitmapEffect>
<DropShadowBitmapEffect Color="Black" Direction="320" ShadowDepth="2" Opacity=".9" Softness="0.3" />
</ContentPresenter.BitmapEffect>
</ContentPresenter>
</Canvas>
</Grid>
<Grid Grid.Row="2" x:Name="RowImg" ShowGridLines="False" VerticalAlignment="Center" Height="Auto">
<Image Source="C:\Users\Zebody\Pictures\thk.jpg"/>
</Grid>
</Grid>
</Viewbox>
</Border>
</ControlTemplate>
My trouble : Viewbox works fine with the grid row's picture and grid's row "label" (resize the font perfectly). But it's not working with rowscroll (marquee part). The font never resize. It seems it's because the canvas. If i remove height and width, resizing works but canvas doesnot fill my custom control.
What i Whant to do : The canvas fill all my custom control and could resize the font when i resize my custom control (in a mainwindow).
Could anyone help me how to do ?
Thx in advance and sorry again for my poor english

Progress bar showing Image, dot at some regular intervals

I need the progress bar which shows both the dot followed by icon after some regular intervals.
I am working on the camera module,when the snap is taken i need to show dot in the progress bar,which show the snap is taken.
Then this snap is passed to the algorthim and it retuns boolen value,then i need to show icon.
if the duration is 1 minutes and the interval is 30 sec ,then in the progress bar control i need to show two dot and two icon in the progress bar.
Please provide me some solutions,below is the XAMl
XAML For the Progress bar
<Window.Resources>
<Style x:Key="ProgressBarStyle" TargetType="ProgressBar">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ProgressBar">
<Border BorderBrush="#BBC6C4" BorderThickness="1" CornerRadius="5" Padding="1">
<Grid x:Name="PART_Track" >
<Rectangle x:Name="PART_Indicator" HorizontalAlignment="Left" RadiusX="5" RadiusY="5">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF1D5666" Offset="1"/>
<GradientStop Color="#FF09B6FF"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Ellipse x:Name="progressdot" HorizontalAlignment="Left" Margin="73,7,0,0" Stroke="#FFA8A49B" Width="8" Height="8"
VerticalAlignment="Top" Grid.Row="1" />
<Image x:Name="imgAcetowhiteness" Margin="89,7,0,0" Source="..\acetowhiteness.png"
Stretch="Fill" Width="15" Height="15" Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Top" />
<Ellipse x:Name="progressdot1" HorizontalAlignment="Left" Margin="180,7,0,0" Stroke="#FFA8A49B" Width="8" Height="8"
VerticalAlignment="Top" Grid.Row="1" />
<Image x:Name="imgAcetowhiteness1" Margin="195,7,0,0" Source="..\acetowhiteness.png"
Stretch="Fill" Width="15" Height="15" Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Top" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<StackPanel Orientation="Vertical">
<ProgressBar x:Name="PBarone" Margin="48,10,10,10" Style="{StaticResource ProgressBarStyle}"/>
<ProgressBar x:Name="PBartwo" Margin="48,20,10,10" Style="{StaticResource ProgressBarStyle}"/>
<ProgressBar x:Name="PBarthree" Margin="48,30,10,10" Style="{StaticResource ProgressBarStyle}"/>
</StackPanel>
</Grid>

Corner-only borders in wpf/xaml

In some xaml, I'd like to have a border that is only out to a few pixels from each corner. So, along the top, the border would be, say, 5 pixels of black at the left edge, then be transparent across the rest of the top until 5 pixels of the right edge, and then the final 5 pixels of the border at the right edge would be black. The intent is to provide some guidance for selection of occasionally transparent things; however, in this application, the presence of a full border would interfere with the content (in the perceptual-visual sense). The corners are not rounded.
Something that looks like this:
-- --
| |
| |
-- --
What type of Brush should I use to achieve this effect?
I've tried a linear gradient, like so:
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="Black" Offset="0" />
<GradientStop Color="Black" Offset="0.01" />
<GradientStop Color="Transparent" Offset="0.0101" />
<GradientStop Color="Transparent" Offset="0.9899" />
<GradientStop Color="Black" Offset="0.99" />
<GradientStop Color="Black" Offset="1" />
</LinearGradientBrush>
Of course, this only does the top left and bottom right. That could be reasonable for the intended application, but the size of the line on each corner is only the same if the region bordered is square (if the bordered area is a long rectangle, for instance, the section of border goes much further along one side than the other).
I did note the MappingMode value of "Absolute" on the gradient brushes. That works well for the top-left corner but not the other corners.
I also tried a RadialGradientBrush, thinking that I could get a ring to hit the corners, but wasn't successful in either centering it correctly or having it hit equal lengths along the sides.
This is part of the ItemContainerStyle in a ListBox, and the border is changed with a Trigger for IsSelected. For this reason, I also can't do borders within borders (within borders, etc.).
Edit #2: I also tried a VisualBrush. I knew I could get the behavior I wanted in a grid (at least, the stretching behavior).
<VisualBrush Stretch="Fill">
<VisualBrush.Visual>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10" MaxWidth="10" MinWidth="10" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="10" MaxWidth="10" MinWidth="10" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="10" MaxHeight="10" MinHeight="10" />
<RowDefinition Height="*" />
<RowDefinition Height="10" MaxHeight="10" MinHeight="10" />
</Grid.RowDefinitions>
<Rectangle Grid.Column="0" Grid.Row="0" Fill="Black" />
<Rectangle Grid.Column="1" Grid.Row="0" Fill="Transparent" />
<Rectangle Grid.Column="2" Grid.Row="0" Fill="Black" />
<Rectangle Grid.Column="0" Grid.Row="1" Fill="Transparent" />
<Rectangle Grid.Column="1" Grid.Row="1" Fill="Transparent" />
<Rectangle Grid.Column="2" Grid.Row="1" Fill="Transparent" />
<Rectangle Grid.Column="0" Grid.Row="2" Fill="Black" />
<Rectangle Grid.Column="1" Grid.Row="2" Fill="Transparent" />
<Rectangle Grid.Column="2" Grid.Row="2" Fill="Black" />
</Grid>
</VisualBrush.Visual>
</VisualBrush>
However, this doesn't work out, either. It seems like sizing doesn't happen in the same way inside a brush. In this case, the size of the Grid in the VisualBrush ended up being 20x20, with the middle transparent parts taking up no space. Setting HorizontalAlignment and VerticalAlignment to Stretch didn't help, either. Stretch="Fill" on the VisualBrush didn't do anything, either.
Edit #1: the wider context:
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
</Style.Resources>
<Setter Property="Margin" Value="3" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderThickness" Value="5" />
<Setter Property="Padding" Value="0" />
<Setter Property="BorderBrush" Value="Fuchsia" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Padding" Value="4" />
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="Black" Offset="0" />
<GradientStop Color="Black" Offset="0.01" />
<GradientStop Color="Transparent" Offset="0.0101" />
<GradientStop Color="Transparent" Offset="0.9899" />
<GradientStop Color="Black" Offset="0.99" />
<GradientStop Color="Black" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
You could use Path ... this will draw something similar to what you're looking for:
<Path Stroke="Black" Stretch="Fill"
Data="M0,0 l10,0 m80,0 l10,0 m0,0 l0,10 m0,80 l0,10 m0,0 l-10,0 m-80,0 l-10,0 m0,0 l0,-10 m0,-80 l0,-10"
Height="100" Width="100" Margin="10" />
Full code sample:
<Window x:Class="WpfApplication1.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">
<Grid>
<Path Stroke="Black" Stretch="Fill"
Data="M0,0 l10,0 m80,0 l10,0 m0,0 l0,10 m0,80 l0,10 m0,0 l-10,0 m-80,0 l-10,0 m0,0 l0,-10 m0,-80 l0,-10"
Height="100" Width="100" Margin="10" />
</Grid>
</Window>
A radial gradient brush would probably achieve what you're looking for. Set the center of the radial brush to the center of your box. Start with a transparent center color, fade from the center to the desired "border color" (black), and then set the radius big enough that the black color only shows up in the corners.
And make sure to set the "gradient" to be very short - don't fade it gradually, but make it sharp.
If you size it right, you'll get an effect similar to that which is (poorly) illustrated below. The red box represents your content. Everything outside that box illustrates what your corners would look like. Make the radius of the "transparent" part bigger, to make your black corners smaller.
Finally; this would pretty much only look good with thin borders. If you have a thick border, it's going to look "funny" at the 'tips' of the corner brush.
Update:
Here's an actual example with some code:
<Border BorderThickness="1" Height="100" Width="100">
<Border.BorderBrush>
<RadialGradientBrush RadiusX="0.6" RadiusY="0.6">
<GradientStop Color="Black" Offset="1"/>
<GradientStop Color="#00000000" Offset="0.99"/>
</RadialGradientBrush>
</Border.BorderBrush>
<Rectangle Fill="Red" />
</Border>
And here's what it looks like:
For rectangular shapes (i.e. not a perfect square), in order to keep the corners the same size, you'd have to scale the RadiusX and RadiusY values accordingly. They should scale with the width/height ratio.
This is a fun question, so here's yet another possibility. I hope you agree that this qualifies as a fully separate answer from my previous one...
You can use a composite set of simple shapes - contained within a Grid - to achieve your desired effect. Layer your "content" box on top of 4 black rectangles, with each black rectangle positioned in the appropriate corner of the grid.
Here's my crappy paint illustration. Once again, the red box indicates your content. Anything outside of that red box is what the user will see as a border.
And the real-life example with code:
<Grid HorizontalAlignment="Center" VerticalAlignment="Center" Width="300" Height="200">
<!-- These rectangles will be the four corner "borders" -->
<Rectangle Fill="Black" Width="50" Height="50" HorizontalAlignment="Left" VerticalAlignment="Top" />
<Rectangle Fill="Black" Width="50" Height="50" HorizontalAlignment="Left" VerticalAlignment="Bottom" />
<Rectangle Fill="Black" Width="50" Height="50" HorizontalAlignment="Right" VerticalAlignment="Top" />
<Rectangle Fill="Black" Width="50" Height="50" HorizontalAlignment="Right" VerticalAlignment="Bottom" />
<!-- Here is the content. The "margin" property will effectively be the thickness of your corner borders. -->
<Rectangle Fill="Red" Margin="2" />
</Grid>
It looks like this:
This has the added benefit of scaling very well; the corner borders will always be the same size, no matter the size of your content. In addition, the border can be any thickness you like, without looking "weird" as the previous, radial-brush answer did.

WPF : Rounded-Corners Images

<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Black">
<!-- Rounded yellow border -->
<Border BorderThickness="3" BorderBrush="Yellow" CornerRadius="10" Padding="2"
HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid>
<!-- Rounded mask (stretches to fill Grid) -->
<Border Name="mask" Background="White" CornerRadius="7"/>
<!-- Main content container -->
<StackPanel>
<!-- Use a VisualBrush of 'mask' as the opacity mask -->
<StackPanel.OpacityMask>
<VisualBrush Visual="{Binding ElementName=mask}"/>
</StackPanel.OpacityMask>
<!-- Any content -->
<Image Source="http://chriscavanagh.files.wordpress.com/2006/12/chriss-blog-banner.jpg"/>
<Rectangle Height="50" Fill="Red"/>
<Rectangle Height="50" Fill="White"/>
<Rectangle Height="50" Fill="Blue"/>
</StackPanel>
</Grid>
</Border>
</Page>
This XAML is from WPF – Easy rounded corners for anything but it doesn't work form me =(
<Border Canvas.Left="55"
Canvas.Top="30"
Width="100"
Height="Auto"
Margin="12,12,8,0"
VerticalAlignment="Top"
BorderBrush="#FF3B5998"
BorderThickness=".5"
CornerRadius="18">
<Border.Effect>
<DropShadowEffect BlurRadius="5"
Opacity=".5"
ShadowDepth="3" />
</Border.Effect>
<Border Name="ReceiverColor"
BorderBrush="#FF96B2E4"
BorderThickness="6"
CornerRadius="15">
<Border Name="Mask"
BorderBrush="#FF3B5998"
BorderThickness=".5"
CornerRadius="13">
<StackPanel>
<StackPanel.OpacityMask>
<VisualBrush Visual="{Binding ElementName=Mask}" />
</StackPanel.OpacityMask>
<Image Name="Receiver" />
</StackPanel>
</Border>
</Border>
</Border>
--- EDIT ---
I make borders sizes to auto and change source of image to an image from a link
when window loaded border size becomes as image size but image not shown !!!
You can define a <Border/> element and set its <Border.Background/>
property to an <ImageBrush/> , set the Borders CornerRadius property and you
are all set!
<Border CornerRadius="8,0,8,0">
<Border.Background>
<ImageBrush Stretch="Fill" ImageSource="ImageSource"/>
</Border.Background>
</Border>
You forgot the Grid that makes the mask and the image siblings and nested the image in the mask. and you forgot to set the background of the mask.
This works:
<Grid>
<Border Canvas.Left="55"
Canvas.Top="30"
Width="100"
Height="Auto"
Margin="12,12,8,0"
VerticalAlignment="Top"
BorderBrush="#FF3B5998"
BorderThickness=".5"
CornerRadius="18">
<Border.Effect>
<DropShadowEffect BlurRadius="5"
Opacity=".5"
ShadowDepth="3" />
</Border.Effect>
<Border Name="ReceiverColor"
BorderBrush="#FF96B2E4"
BorderThickness="6"
CornerRadius="15">
<Grid>
<Border Name="Mask"
Background="White"
BorderBrush="#FF3B5998"
BorderThickness=".5"
CornerRadius="13">
</Border>
<StackPanel>
<Image Name="Receiver"
Source="/Images/test.jpg" />
<StackPanel.OpacityMask>
<VisualBrush Visual="{Binding ElementName=Mask}" />
</StackPanel.OpacityMask>
</StackPanel>
</Grid>
</Border>
</Border>
</Grid>
in wpf this one works for me
<Ellipse Width="50" Height="50">
<Ellipse.Fill>
<ImageBrush ImageSource="http://chriscavanagh.files.wordpress.com/2006/12/chriss-blog-banner.jpg" />
</Ellipse.Fill>
</Ellipse>
None of the above answers worked for me completely. I was trying to implement rounded corners on image which could be resized and has properties Stretch="UniformToFill" VerticalAlignment="Center" and HorizontalAlignment="Center".
The center alignments keeps the middle part cropped as opposed to bottom and right side being cropped, when image is resized. Solutions with image brush were working but I was facing problem in keeping the content at center cropped.
The marked answer has a problem with transparent non rectangular images as the "mask" border will end up showing as white background. Following was the imlementation which worked for me:
<Grid>
<WrapPanel Name ="container">
<Image Source="sample_image.png" VerticalAlignment="Center" HorizontalAlignment="Center" Stretch="UniformToFill"/>
<WrapPanel.OpacityMask>
<VisualBrush >
<VisualBrush.Visual>
<Border Height="{Binding ElementName=container, Path=ActualHeight}"
Width="{Binding ElementName=container, Path=ActualWidth}"
Background="White" CornerRadius="15" />
</VisualBrush.Visual>
</VisualBrush>
</WrapPanel.OpacityMask>
</WrapPanel>
</Grid>
You can use an ellipse like how Usman Ali has said (I thought this myself and I didn't take it from him)
It's very simple, make an ellipse with the properties you want, then set the fill to an imagebrush with your desired image like this in XAML:
<Ellipse Height="Auto" Width="100">
<Ellipse.Fill>
<ImageBrush ImageSource="YOUR IMAGE SOURCE/LINK HERE"/>
</Ellipse.Fill>
</Ellipse>
In C#, if in any case you want to do in C#:
Ellipse YourEllipseName = new Ellipse
{
Height = 50,
Width = 50,
StrokeThickness = 0,
Fill = new ImageBrush
{
Stretch = Stretch.Uniform,
ImageSource = new BitmapImage(new Uri("YOUR IMAGE SOURCE HERE"))
}
};
<Grid Background="Black">
<Rectangle RadiusX="20" RadiusY="20"
Width="130"
Height="130">
<Rectangle.Fill>
<ImageBrush x:Name="myImage" ImageSource="C:\Path\Desktop\visual-studio-2010-logo.png"/>
</Rectangle.Fill>
</Rectangle>
</Grid>

Style a border with a different brush color for each corner

I have created a static resource defining the border of a specific item in my xaml, but I can't find a good way to define a unique color for each side!
xaml:
<Border Style="{StaticResource SidePanelBorder}">
<!-- rest of the xaml -->
</Border>
StaticResource:
<Style x:Key="SidePanelBorder">
<Setter Property="Control.BorderBrush" Value="#FF363636" />
<Setter Property="Control.BorderThickness" Value="1" />
</Style>
But I want to define one color for each side of the border, and eventually also a different Border thickness.
Any good techniques out there doing this?
Seems very hacky, but you could define borders within borders, and make only 1 side have a thickness. For example
<Border BorderThickness="0,0,0,10" BorderBrush="Green">
<Border BorderThickness="0,0,10,0" BorderBrush="Blue">
<Grid>
<Button>Hello</Button>
</Grid>
</Border>
</Border>
would give a green border on the bottom and a blue border to the right. Isn't the prettiest piece of Xaml though.
Another solution using one Border and a VisualBrush, allowing setting the Border's CornerRadius and BorderThickness:
<Border BorderThickness="10" CornerRadius="10" HorizontalAlignment="Right" Height="150" VerticalAlignment="Bottom" Width="150" Margin="0,0,92.666,42.667">
<Border.BorderBrush>
<VisualBrush>
<VisualBrush.Visual>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Path x:Name="ColoredBorderLeft" Data="M0,0 L0,0 1,0.5 L1,0.5 0,1" Fill="Blue" Stretch="Fill" Grid.RowSpan="2"/>
<Path x:Name="ColoredBorderRight" Data="M1,0 L1,0 0,0.5 L0,0.5 1,1" Fill="Red" Stretch="Fill" Grid.Column="1" Grid.RowSpan="2"/>
<Path x:Name="ColoredBorderTop" Data="M0,0 L0,0 0.5,1 L0.5,1 1,0" Fill="Green" Stretch="Fill" Grid.ColumnSpan="2"/>
<Path x:Name="ColoredBorderBottom" Data="M0,1 L0,1 0.5,0 L0.5,0 1,1" Fill="Yellow" Stretch="Fill" Grid.Row="1" Grid.ColumnSpan="2"/>
</Grid>
</VisualBrush.Visual>
</VisualBrush>
</Border.BorderBrush>
</Border>
The Grid is needed to prevent the tips of the triangle Paths to "push through" into the border.
The Path.Name's can be used for DataBinding or setting the color from code behind.
you can have a DockPanel and can put 4 Borders inside it, each docked to different side.
like:
<DockPanel LastChildFill="true">
<Border DockPanel.Dock="Left" Background="Red"/>
<Border DockPanel.Dock="Top" Background ="Blue"/>
<Border DockPanel.Dock="Right" Background ="Yellow"/>
<Border DockPanel.Dock="Bottom" Background ="Green"/>
<Grid>
...........your control here
</Grid>
</DockPanel>
If you use a Grid you can have Border's overlay on one another to achieve the same affect. Just set the border thickness of the border color you want to show and have the other border thickness be 0.
<UserControl.Resources>
<Style x:Key="GreenBorder" TargetType="Border">
<Setter Property="BorderBrush" Value="Green" />
<Setter Property="BorderThickness" Value="1,1,1,0" />
</Style>
<Style x:Key="RedBorder" TargetType="Border">
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="BorderThickness" Value="0,0,0,1" />
</Style>
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border Grid.Column="0" Grid.Row="0" Style="{StaticResource GreenBorder}">
<!-- Content goes here -->
</Border>
<Border Grid.Column="0" Grid.Row="0" Style="{StaticResource RedBorder}">
</Border>
</Grid>
This will give a Green border to the left, top and right borders, but a Red border to the bottom border of the Grid cell.
there's no easy way to do this without writing your own control or subclassing border

Resources