Acrobat-like PopUp in WPF - c#

Im recently working on some simple Imageviewer.
Now it came to my mind, it might be a nice feature, to do some context-sensitve actions like Zooming and rotating.
To implement these functions is not my problem, but the ContextMenu is.
I've decided to not use a ContextMenu-Element, instead im going to use a popup.
Reasons for PopUp:
Less Styling
Better Positioning
IsOpen is Bindable (ContextMenu is NOT bindable on IsOpen against all Articles regarding this)
Here comes the trouble:
<Image x:Name="PART_ImgCurrent" VerticalAlignment="Center" HorizontalAlignment="Center" Stretch="Uniform" Grid.Row="0" Grid.Column="0"
Source="{Binding ElementName=PART_PreviewPanel, Path=SelectedItem.Source}">
<Image.LayoutTransform>
<RotateTransform Angle="0"></RotateTransform>
</Image.LayoutTransform>
<Image.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="PART_ImgCurrent" Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:3" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</Image>
<Popup IsHitTestVisible="False" Focusable="False" PlacementTarget="{Binding ElementName=PART_ImgCurrent}" AllowsTransparency="True" StaysOpen="True"
IsOpen="{Binding ElementName=PART_ImgCurrent, Path=IsMouseOver, Mode=OneWay}"
Placement="Right" HorizontalOffset="-42" VerticalOffset="2">
<StackPanel Opacity="0.5" VerticalAlignment="Stretch">
<Button Content="Ugly Button" Height="40" Width="40"></Button>
<Button Content="Ugly Button" Height="40" Width="40"></Button>
<Button Content="Ugly Button" Height="40" Width="40"></Button>
</StackPanel>
</Popup>
As you can see, im binding IsOpen of Popup to IsMouseOver on Image which results in a funny Disco-BlinkenLights-Behavior when i try to click a button inside the Popup.
What has this to do with the Title?
AcrobatReader has this
This is almost exactly the behavior im looking for. How is this thing called?
Or had someone ever similar issues and could provide a solution?

Sorry for the delay, soon as I thought I had a second I got busy again. Anyway, here's one of several ways I can think of accomplishing your goal, give it a shot. I sort of assumed it may not be just images you want this for and if you threw the resource stuff in a dictionary and kept your naming consistent (or even better, just target the nested UIElement) you could use it all over the place. Notice the Grid is acting as what would be the Image in this example.
I generally make things open for future added interactions and stuff, so in this case I would probably just make the image source the background brush for Grid or place it as a child. That way if you decide to add other objects in there or say other effects and stuff you've got a good start point.
Anyway I digress, so try out the concept example below and see if it's what you're after. If not, like I said there's several other ways I can think of to accomplish your goal so just let me know. :)
<!-- HitTestVisibility Area -->
<Grid x:Name="ImagePlaceholder"
Height="500" Width="500"
Background="LightBlue">
<Grid.Resources>
<Storyboard x:Key="OnMouseEnter">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="FakePopUp">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="OnMouseLeave">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="FakePopUp">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</Grid.Resources>
<Grid.Triggers>
<EventTrigger RoutedEvent="UIElement.MouseEnter">
<BeginStoryboard Storyboard="{StaticResource OnMouseEnter}"/>
</EventTrigger>
<EventTrigger RoutedEvent="UIElement.MouseLeave">
<BeginStoryboard Storyboard="{StaticResource OnMouseLeave}"/>
</EventTrigger>
</Grid.Triggers>
<!-- Overlay -->
<Border Name="FakePopUp" Visibility="Collapsed"
Margin="0,0,0,25" Background="SlateGray"
Height="50" CornerRadius="20" Padding="10"
HorizontalAlignment="Center" VerticalAlignment="Bottom">
<StackPanel Orientation="Horizontal">
<Button Content="Eins Bier"/>
<Button Content="Zwei Bier" Margin="10,0"/>
<Button Content="Drei Bier"/>
</StackPanel>
</Border>
</Grid>
I went with Storyboards attached to the parent instead of direct triggers with TargetName like I said, because I could think of a bunch of other instances features might want to be added that would make sense. Even something simple like adding a transition duration for a nice fade effect or maybe a translate y to slide it up while fading etc, etc, etc.
Anyway, hope this helps. Cheers!

Related

How to do flashing rectangle outline for a WPF datagrid cell?

Basically I have a WPF datagrid, and I want to add a flashing outline to a specific cell in XAML via binding that will make this visible. I know how to do this except the flashing part.
How can I do that so that the rectangle outline flashes for a specific duration like 2 seconds, so it goes from opacity = 0 to 1 and then 0 and so on.
Does WPF have a mechanism for this?
<Border BorderThickness="1" BorderBrush="Red">
<Rectangle Fill="#FF5A9AE0"
Stretch="UniformToFill"
ClipToBounds="True"/>
</Border>
This will flash the border on and off.
<Border Name="MyBorder" BorderThickness="1" BorderBrush="Red">
<Border.Triggers>
<EventTrigger RoutedEvent="Border.Loaded">
<BeginStoryboard>
<Storyboard>
<ThicknessAnimationUsingKeyFrames
Storyboard.TargetName="MyBorder"
Storyboard.TargetProperty="BorderThickness"
AutoReverse="True" RepeatBehavior="Forever">
<DiscreteThicknessKeyFrame KeyTime="0:0:00.00" Value="1" />
<DiscreteThicknessKeyFrame KeyTime="0:0:00.25" Value="5" />
<DiscreteThicknessKeyFrame KeyTime="0:0:00.50" Value="1" />
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
<Rectangle Fill="#FF5A9AE0" Stretch="UniformToFill" ClipToBounds="True" />
</Border>
There are lots of animation options, so please have a look at https://learn.microsoft.com/en-us/dotnet/desktop/wpf/graphics-multimedia/animation-overview?view=netframeworkdesktop-4.8 for details/ideas.

WPF: add blur effect on button when mouse is on that button-MouseEnter

I'm trying to make a simple animation - when mouse cursor is on button I want to add blur effect on that button.
So far I have this.:
<Button x:Name="button_Copy" Content="Leaderboard" HorizontalAlignment="Left" Margin="311,217,0,0" VerticalAlignment="Top" Width="139" Height="34" Background="{x:Null}" BorderBrush="{x:Null}" FontSize="22" FontWeight="Bold" Foreground="#FFE2DBDB" IsHitTestVisible="True" Click="button_Copy_Click">
<Button.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation From="10" To="0" Duration="0:0:0.1"
Storyboard.TargetName="blurEffect" Storyboard.TargetProperty="Radius"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
Build is succesfull, but when I take cursor over that button program immediately crashes... Any idea how to fix this?
I see you probably took your example from here.
You are missing the object BlurEffect as shown within the TextBox item as below:
<TextBlock Name="TxtSample" TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" Text="This is a sample and first test freetext">
<TextBlock.Effect>
<BlurEffect Radius="10" x:Name="blurEffect"/>
</TextBlock.Effect>
</TextBlock>

Is it Possible to animate path.Data

I have code something like this:
<Path x:Name="arrow" StrokeThickness="3" Stroke="Black" Data="M34,115 C45,106 91,119 105,112 119,105 172,75.004352 188,82.003591" />
what I want is to animate the Data property of the path. I'm searching this from last two days didn't find a solution.
what I actually want is to show path bit by bit.
Does anyone have any Idea?
"what I actually want is to show path bit by bit"
Do you mean something like this?
<Grid VerticalAlignment="Center" HorizontalAlignment="Center" >
<Grid.Resources>
<Storyboard x:Key="CWTrace">
<!-- To run opposite direction, just swap the 'From' and 'To' values. -->
<DoubleAnimation BeginTime="00:00:0.5" RepeatBehavior="Forever"
Storyboard.TargetName="arrow"
Storyboard.TargetProperty="StrokeDashOffset"
Duration="0:0:5" From="100" To="0"/>
</Storyboard>
</Grid.Resources>
<Grid.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource CWTrace}"/>
</EventTrigger>
</Grid.Triggers>
<Path x:Name="arrow"
StrokeDashOffset="0" StrokeDashArray="100"
StrokeThickness="3" Stroke="Black"
Data="M34,115 C45,106 91,119 105,112 119,105 172,75.004352 188,82.003591"/>
</Grid>
Obviously remove the RepeatBehavior for a one time anim, and tinker with values to get exactly what you're after. Cheers.

Perform Event Trigger on DataGrid for DragEnter causing XAML exception

I am working on a c# wpf project and I have run in to a problem relating to firing an trigger within the XAML.
What I am trying to achieve is when the drags a file into the grid, it should animate the background colour change but for some reason it keeps on throwing an exception as soon as I run the program. I am getting the following error:
'Provide value on
'System.Windows.Baml2006.TypeConverterMarkupExtension' threw an
exception.' Line number '9' and line position '14'.
Below is the XAML code
<UserControl x:Class="ReportReader.UserControls.ReportDragDropControl"
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">
<Grid AllowDrop="True" DragDrop.DragOver="Grid_DragOver"
DragDrop.DragEnter="Grid_DragEnter" DragDrop.Drop="Grid_Drop" DragDrop.DragLeave="Grid_DragLeave">
<Grid.Triggers>
<EventTrigger RoutedEvent="Grid.DragEnter">
<BeginStoryboard>
<Storyboard>
<ColorAnimation To="#cecece" Storyboard.TargetProperty="(Grid.BackgroundColor).(SolidColorBrush.Color)" FillBehavior="Stop" Duration="0.0.1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<TextBlock Margin="12,12,20,12" Name="txtDragDropStatus" Text="Drag file here or use file menu to load your report" TextAlignment="Center" FontSize="30" FontWeight="Bold" TextWrapping="WrapWithOverflow" Width="835" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</UserControl>
Thanks for any help you can provide.
There are two errors in your XAML file -
BackgroundColor is not a Dependency Property, instead use Background.
0.0.1 is not a valid value for TimeSpan. It should be 0:0:1.
This will work fine -
<ColorAnimation To="#cecece"
Storyboard.TargetProperty="(Grid.Background)
.(SolidColorBrush.Color)"
FillBehavior="Stop" Duration="0:0:1" />
Also, to allow animation on background property, you should set it to some default value.
<Grid Background="White"/>
I tried with this sample and its working fine on drag enter -
<Grid AllowDrop="True" Background="White" DragDrop.DragEnter="Grid_DragEnter">
<Grid.Triggers>
<EventTrigger RoutedEvent="Grid.DragEnter">
<BeginStoryboard>
<Storyboard>
<ColorAnimation To="#cecece"
Storyboard.TargetProperty="(Grid.Background).
(SolidColorBrush.Color)"
FillBehavior="Stop" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
/EventTrigger>
</Grid.Triggers>
<TextBlock Margin="12,12,20,12" Name="txtDragDropStatus"
Text="Drag file here or use file menu to load your report"/>
</Grid>

Animation limited by panel

It's a little hard to describe but I'll try my best.
I have a control which has an image and a label and it needs to have 2 states ("Big", and "Small").
On the "Big" state the image should be centered at the top of the control, and the label should be center below (Just like a dock with an image and a label docked to the top).
On the "Small" state the image should be smaller and at the top left of the control, and the label should be right next to it.
The big state should look like so:
And the small state:
And the tricky part: when I switch between them I need it to animate over 0.3s.
There is no panel I found suitable for this.
DockPanel is a good solution for both of these states, but it can't animate it.
Canvas can animate it, but doesn't have a proper layout (can't center them so easily).
What would be the best way to do it?
In WPF no animation alignment, the only thing that can come up - it ThicknessAnimation. But you can use the DiscreteObjectKeyFrame to set the alignment. Below is a simple demonstration in which to Label set VerticalAlignment in Bottom:
<Grid>
<Grid.Triggers>
<EventTrigger SourceName="Small" RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetName="Test" Storyboard.TargetProperty="VerticalAlignment">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<VerticalAlignment>Bottom</VerticalAlignment>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<Label x:Name="Test" Content="Test" Width="300" Height="300" Background="Aqua" VerticalAlignment="Top" HorizontalAlignment="Center" />
<Button Name="Small" Content="Small" Width="100" Height="30" HorizontalAlignment="Right" VerticalAlignment="Top" />
</Grid>
Using it in combination with standard animations, such as DoubleAnimation, I think you'll be able to achieve this goal.

Categories