WPF: How to draw a rectangle like in Excel copy mode? - wpf

In Excel, when you press Ctrl+C, the current cell is surrounded by a rectangle with broken line seemingly running around. Any tip on how to make it in WPF?

What you're looking for is usually called a "Marching Ants Border". There are already a few implementations out there for WPF.
Here is one from Patric Johansson's blog and another from codeproject
Added main code from CodeProject for future references:
<Window.Resources>
<Storyboard x:Key="MarchingAnts">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="rectangle"
Storyboard.TargetProperty="(Shape.StrokeDashOffset)"
RepeatBehavior="Forever">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.5000000"
Value="10"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource MarchingAnts}"/>
</EventTrigger>
</Window.Triggers>
<Grid x:Name="LayoutRoot">
<Canvas x:Name="canvas" Background="#FF262626">
<Rectangle Fill="#14FFFFFF" StrokeDashArray="5"
Stroke="#FFFFFFFF"
x:Name="rectangle" Width="50" Height="50"
StrokeDashOffset="0" StrokeThickness="1"
RadiusX="0" RadiusY="0"
Canvas.Left="0" Canvas.Top="0"/>
<TextBlock Width="Auto" Height="Auto"
FontFamily="Century Gothic"
FontSize="48" Foreground="#FF5B5B5B"
Text="MARCHING ANTS" TextWrapping="Wrap"
Canvas.Top="182" Canvas.Left="79"/>
</Canvas>
</Grid>

Related

How To add control from ToolBox on user control in a form

I have created a user control like below ,after adding this control on a from I want to add controls like button etc on the rectangle region from ToolBox. My User control is like this.
<UserControl.Resources>
<Storyboard x:Key="OpenMenu">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty ="(FrameworkElement.Width)" >
<EasingDoubleKeyFrame KeyTime="0:0:0:.5" Value="500"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="CloseMenu">
<DoubleAnimationUsingKeyFrames BeginTime="0:0:0:.4" Storyboard.TargetProperty ="(FrameworkElement.Width)" >
<EasingDoubleKeyFrame KeyTime="0:0:0:.5" Value="70"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="OpenMenuExtend">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty ="(FrameworkElement.Width)" Storyboard.TargetName="RightVMenu" >
<EasingDoubleKeyFrame KeyTime="0:0:0:.5" Value="600"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="MenuExtendLstView">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty ="(FrameworkElement.Width)" Storyboard.TargetName="RightVMenu" >
<EasingDoubleKeyFrame KeyTime="0:0:0:.5" Value="740"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</UserControl.Resources>
<UserControl.Style>
<Style TargetType="UserControl" >
<Style.Triggers >
<EventTrigger RoutedEvent="Mouse.MouseEnter" >
<EventTrigger.Actions>
<BeginStoryboard Storyboard="{StaticResource OpenMenu}">
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave" >
<EventTrigger.Actions>
<BeginStoryboard Storyboard="{StaticResource CloseMenu}">
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</UserControl.Style>
<Grid Width="Auto" Height="Auto">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="90*"/>
</Grid.ColumnDefinitions>
<Path Grid.ColumnSpan="1" Fill="#FF5383D6" Height="Auto" Stretch="Fill" Width="Auto">
<Path.Data>
<PathGeometry Figures="M 127 287 109 287 74 264V 152 41 l 33 -20 20 0 -1e-10 0 z" FillRule="NonZero"/>
</Path.Data>
</Path>
<Button Content="Button" HorizontalAlignment="Left" Margin="10,69,0,0" VerticalAlignment="Top" Width="40"/>
<Button Content="Button" HorizontalAlignment="Left" Margin="10,119,0,0" VerticalAlignment="Top" Width="40"/>
<Rectangle Grid.Column="2" Fill="GreenYellow"/>
</Grid>
I want to add controls from ToolBox on this control after adding control on a form.
Here in the green Rectangle region.
Please help how to acheive this.
Thanks

Why my Storyboard run when I move my cursor from an element to another? [duplicate]

This question already has answers here:
Detect mouse directly over border in WPF
(2 answers)
Closed 8 years ago.
I build a small control with a panel of two buttons. When I hover the control I want to show the panel and hide it when I leave. Everything works great, but I have one bug. When I move the cursor from the TextBlock to the Image my Storyboard run again. I dont understand why because both of them are inside the control. I try to add a Border to wrap the control, but it didnt work.
<UserControl.Resources>
<Storyboard x:Key="Show">
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"
Storyboard.TargetName="QuickPanel">
<EasingDoubleKeyFrame KeyTime="0" Value="18"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Hide">
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"
Storyboard.TargetName="QuickPanel">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="18"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</UserControl.Resources>
<UserControl.Triggers>
<EventTrigger RoutedEvent="Border.MouseEnter">
<BeginStoryboard Storyboard="{StaticResource Show}"/>
</EventTrigger>
<EventTrigger RoutedEvent="Border.MouseLeave">
<BeginStoryboard Storyboard="{StaticResource Hide}"/>
</EventTrigger>
</UserControl.Triggers>
<Border Width="144" Height="36" ClipToBounds="True" BorderThickness="0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Image Source="http://www.streamplay.fr/thumb/fanart/3000/3000/1321396.jpg"
VerticalAlignment="Center" HorizontalAlignment="Center" Margin="2"
Stretch="UniformToFill" Height="34" Width="34"/>
<Grid Grid.Column="1">
<StackPanel VerticalAlignment="Center" Margin="6,0,0,0">
<TextBlock FontSize="12" FontWeight="DemiBold">Sample Title</TextBlock>
<TextBlock FontSize="10" Text="{Binding Title, Mode=TwoWay}"></TextBlock>
</StackPanel>
</Grid>
<StackPanel x:Name="QuickPanel" Grid.Column="1" Width="18" HorizontalAlignment="Right" RenderTransformOrigin="0.5,0.5">
<StackPanel.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform X="18"/>
</TransformGroup>
</StackPanel.RenderTransform>
<Button x:Name="button" Height="18" Content="p" IsDefault="True" />
<Button x:Name="button1" Height="18" Content="k" />
</StackPanel>
</Grid>
</Border>
Any idea how to change this ?
You need to set a background to your Border element UI:
Border Background="Transparent" ...
If you don't set the background, the space between image and textblock is your parent window.

Animation during SelectionChanged

I have a TabControl where each TabItem has a separate control as its Content element. Now, I can easily execute a storyboard when switching to a tab by using a UserControl.Loaded EventTrigger. However, I also want to run an exit animation when switching from one tab to another (i.e. allow the old Content control to animate away, followed by the new Content control's entrance animation).
Is it possible to do this with standard WPF constructs?
If not, how would I go about developing a custom solution that handles this?
Edit:
I went ahead and made a modified TabControl that extends the base TabControl and overrode its OnSelectionChanged method as follows:
protected override void OnSelectionChanged(SelectionChangedEventArgs e)
{
if (e.AddedItems.Count == 1 && e.RemovedItems.Count == 1)
{
var oldTab = e.RemovedItems[0] as TabItem;
if (oldTab != null)
{
var exitStoryboard = /** code to find the storyboard **/
if (exitStoryboard != null)
{
exitStoryboard.Completed = (_, __) => base.OnSelectionChanged(e);
exitStoryboard.Begin();
return;
}
}
}
base.OnSelectionChanged(e);
}
This works, except when I click between the tabs too quickly in which case the base.OnSelectionChanged never gets called, presumably because the storyboard is not active any more. Tips?
Here's a solution for 2 tabs, the general idea is to pop up an image of the last tab after the selection changes, and then fade the current tab in.
With a little effort you could probably genericize it for any number of tabs by tracking the last tab for the VisualBrush in a property instead of the hardcoded "other" tab used here.
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<TabControl>
<TabItem x:Name="tab1" Header="Tab 1">
<Border Background="Transparent">
<Grid>
<TextBlock FontSize="40" Foreground="Red" Text="Tab 1 Contents">
<TextBlock.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity">
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="0.0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimation
Duration="0:0:0.25"
From="1"
Storyboard.TargetName="tab2Shadow"
Storyboard.TargetProperty="Opacity"
To="0"/>
<DoubleAnimation
BeginTime="0:0:0.25"
Duration="0:0:0.25"
From="0"
Storyboard.TargetProperty="Opacity"
To="1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
<Rectangle x:Name="tab2Shadow">
<Rectangle.Fill>
<VisualBrush
AlignmentX="Left"
AlignmentY="Top"
AutoLayoutContent="False"
Stretch="None"
Visual="{Binding ElementName=tab2, Path=Content}"/>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Border>
</TabItem>
<TabItem x:Name="tab2" Header="Tab 2">
<Border Background="Transparent">
<Grid>
<TextBlock FontSize="40" Foreground="Red" Text="Tab 2 Contents">
<TextBlock.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity">
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="0.0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimation
Duration="0:0:0.25"
From="1"
Storyboard.TargetName="tab1Shadow"
Storyboard.TargetProperty="Opacity"
To="0"/>
<DoubleAnimation
BeginTime="0:0:0.25"
Duration="0:0:0.25"
From="0"
Storyboard.TargetProperty="Opacity"
To="1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
<Rectangle x:Name="tab1Shadow">
<Rectangle.Fill>
<VisualBrush
AlignmentX="Left"
AlignmentY="Top"
AutoLayoutContent="False"
Stretch="None"
Visual="{Binding ElementName=tab1, Path=Content}"/>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Border>
</TabItem>
</TabControl>
</Grid>
You can use the TabControl.SelectionChanged event.
You can define a custom style for your tabcontrol and do animation on Selector.SelectionChanged RoutedEvent
<Style x:Key="{x:Type TabControl}"
TargetType="TabControl">
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabControl">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="40" />
<RowDefinition />
</Grid.RowDefinitions>
<UniformGrid Grid.Row="0"
Rows="1"
IsItemsHost="True" />
<ContentPresenter x:Name="TabContent"
Grid.Row="2"
Content="{TemplateBinding SelectedContent}">
</ContentPresenter>
</Grid>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="Selector.SelectionChanged">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation From="0"
To="1"
Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="TabContent"
Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

How to display wpf Splash screen inside main window?

WPF Splash screen getting displayed just as an image not as a window...i mean ...it looks like first an image comes..then...my window(i mean window with a bar at top) comes in...How do I display image inside my main window
just try this
<Window x:Class="WpfApplication43.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="600" Width="800" AllowsTransparency="True" WindowStyle="None" Background="{x:Null}" HorizontalAlignment="Center" VerticalAlignment="Center" WindowStartupLocation="CenterScreen">
<Window.Resources>
<Storyboard x:Key="OnLoaded1">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="splashGrid" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.2000000" Value="1"/>
<SplineDoubleKeyFrame KeyTime="00:00:03" Value="1"/>
<SplineDoubleKeyFrame KeyTime="00:00:04" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:03.6000000" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:04.3000000" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource OnLoaded1}"/>
</EventTrigger>
</Window.Triggers>
<Grid>
<Grid x:Name="LayoutRoot" Opacity="0" Background="#FF180A0A"/>
<Grid RenderTransformOrigin="0.5,0.5" Width="400" Height="300"
x:Name="splashGrid"
Opacity="0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="0,0,0,0" >
<Border BorderBrush="Black" BorderThickness="0" CornerRadius="10" Background="#FFAD6868">
<Grid Margin="5">
<Image Margin="0" Source="The_Midnight_Sun_by_Isilmetriel.jpg" Stretch="Fill"/>
</Grid>
</Border>
</Grid>
</Grid>

With WPF, how to link an animation with a ContentControl?

I don't know how to link successfully a StoryBoard to a TranslateTransform that is part of a ContentControl. I always get the following error when I try to run my StoryBoard:
'RenderTransform' property does not point to a DependencyObject in path '(Children).[0].(Content).(0).(1)'.
I guess I don't know how to define a TargetProperty properly! I tried many different paths but always failed. Here is a simplified version of my code:
The DataTemplate:
<DataTemplate x:Key="bdAnswer">
<Border>
<Border.RenderTransform>
<TranslateTransform X="0" Y="0"/>
</Border.RenderTransform>
</Border>
</DataTemplate>
The Canvas where the DataTemplate is used:
<Canvas x:Name="cnvGame">
<ContentControl ContentTemplate="{StaticResource bdAnswer}" />
<ContentControl ContentTemplate="{StaticResource bdAnswer}" />
</Canvas>
And my StoryBoard:
<Storyboard x:Key="sbGame">
<DoubleAnimationUsingKeyFrames
BeginTime="00:00:00"
Storyboard.TargetName="cnvGame"
Storyboard.TargetProperty="(Children)[0].(Content).(UIElement.RenderTransform).(TranslateTransform.Y)" />
</Storyboard>
Many thanks!
That all depends on how you intend to trigger that Storyboard. You were kind of vague, so it might not fit your situation. Everything is contained within the DataTrigger, everything is within the same scope and ascertaining that translate Y property is easy this way.
<DataTemplate x:Key="bdAnswer">
<DataTemplate.Resources>
<Storyboard x:Key="Storyboard1">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="border" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
<SplineDoubleKeyFrame KeyTime="00:00:00.2000000" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</DataTemplate.Resources>
<Border x:Name="border" RenderTransformOrigin="0.5,0.5">
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform Y="10"/>
</TransformGroup>
</Border.RenderTransform>
<TextBlock Text="A Bar of Foo"/>
</Border>
<DataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard x:Name="Storyboard1_BeginStoryboard" Storyboard="{StaticResource Storyboard1}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="Storyboard1_BeginStoryboard"/>
</Trigger.ExitActions>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
Here is an example of something I have used
<DataTemplate x:Key="PM_ORDERSTemplate">
<DataTemplate.Resources>
<Storyboard x:Key="OnChecked1">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="image" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="OnUnchecked1">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="image" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="OnLoaded1">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="image">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</DataTemplate.Resources>
<RadioButton x:Name="radioButton" GroupName="OrderSelect" BorderThickness="1,1,1,1" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" Style="{DynamicResource RadioButtonOrderPicker}" Checked="RadioButton_Checked" Template="{DynamicResource RadioButtonControlTemplate1}" Margin="5,5,5,0" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="{x:Null}">
<Border x:Name="bOrderPicker" BorderThickness="5,5,5,5" BorderBrush="{DynamicResource DNP-MediaPlayerBorderColor}" CornerRadius="10,10,10,10" BitmapEffect="{DynamicResource DNP-OrderPickerShadow}" MinHeight="45" Padding="5" d:LayoutOverrides="Width, Height, GridBox" >
<Border.Background>
<LinearGradientBrush EndPoint="125000,1704.038" StartPoint="125000,0" MappingMode="Absolute" SpreadMethod="Pad">
<GradientStop Color="#19FFFFFF" Offset="0"/>
<GradientStop Color="#34FFFFFF" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image x:Name="image" Width="40" Height="40" Source="Res/Branding/icon_check.png" Margin="2"/>
<Grid Margin="0,0,0,0" d:LayoutOverrides="Width" Grid.Column="1" >
<Label Content="{Binding ORDER_ID.Value" />
</Grid>
</Grid>
</Border>
</RadioButton>
<DataTemplate.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded" SourceName="radioButton">
<BeginStoryboard x:Name="OnUnchecked1_BeginStoryboard1" Storyboard="{StaticResource OnLoaded1}"/>
</EventTrigger>
<EventTrigger RoutedEvent="ToggleButton.Checked" SourceName="radioButton">
<BeginStoryboard Storyboard="{StaticResource OnChecked1}"/>
</EventTrigger>
<EventTrigger RoutedEvent="ToggleButton.Unchecked" SourceName="radioButton">
<BeginStoryboard x:Name="OnUnchecked1_BeginStoryboard" Storyboard="{StaticResource OnUnchecked1}"/>
</EventTrigger>
</DataTemplate.Triggers>
</DataTemplate>

Resources