WPF Popup Closing Animatiom - c#

<Popup
AllowsTransparency="True"
Focusable="False"
PopupAnimation="Slide"
Width="{Binding ElementName=grid,Path=ActualWidth}"
Height ="{Binding ElementName=grid,Path=ActualHeight}"
Name="popup"
Placement="Relative"
PlacementTarget="{Binding grid}" >
</Popup>
This popup opens by slide animation perfectly when i set it's IsOpen Property to True. but why Popup closes immediately without any animation.
Is there a way to animate Popup closing ?

The current WPF implementation only supports the PopupAnimation.Fade animation for closing the popup.
You can check this in the source code:
if (animation == PopupAnimation.Fade)
{
_popupRoot.Value.SetupFadeAnimation(AnimationDelayTime, visible);
return true;
}
else if (visible) // only translate when showing popup
{
// translate the content
_popupRoot.Value.SetupTranslateAnimations(animation, AnimationDelayTime, AnimateFromRight, AnimateFromBottom);
return true;
}
For PopupAnimation.Fade, both the showing and the closing are animated. For other animation types, only the visible (showing) state is animated.
You cannot change this behavior. You could of course attach a custom animation to your content, but the popup will be closed immediately anyway, so you won't see it:
if (!animating)
_secHelper.HideWindow();
If you can, use adorners instead of popups. There, you can setup your animation as you need. Alternatively, use the fade animation for popups.

Related

[WPF]How to close popup

I'd like to close a popup automatically with controling StaysOpen value which is popup property. I've been opening it whenever text is entered or left mouse button is clicked.
StaysOpen is set to false.
<Grid>
<TextBox x:Name="textBox" PreviewMouseLeftButtonUp="textBox_PreviewMouseLeftButtonUp"/>
<Popup IsOpen="{Binding IsOpen, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" OpacityMask="Transparent" StaysOpen="{Binding StaysOpen, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
AllowsTransparency="True" PlacementTarget="{Binding ElementName=textBox}">
<Border CornerRadius="5" Background="#FF303030" Width="{Binding ActualWidth, ElementName=textBox}">
...
</Border>
</Popup>
</Grid>
private void textBox_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if ((sender as TextBox).Text.Length > 0)
{
IsOpen = !IsOpen;
}
}
When text is entered in Textbox with Popup's IsOpen is true, can be closed automatically popup when clicked out side of the control. But, in a state of textBox_PreviewMouseLeftButtonUp function call with same situations, wouldn't be closed it automatically.(also IsOpen is true)
If i change to e.handel = true in textBox_PreviewMouseLeftButtonUp, then can be closed automatically, through clicking the outside of it. But it have serious problem on that, can not choose any of controls in the popup. so can not use this way.
How can I safely close the popup automatically by clicking out side of control?
You can use the TextBox's LostKeyboardFocus event, which fires when the TextBox is no longer the destination for keyboard input (i.e. when the user clicks or tabs away from the control).
private void textBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
IsOpen = false;
}
Also, for opening the popup, I might recommend using GotKeyboardFocus. PreviewMouseLeftButtonUp will only work if the user sets focus by left-clicking, but the user could also use tab, etc.
Not perfect, but I solved it.
I added MouseLeftButtonUpEvent instead of PreviewMouseLeftButtonUp.
textBox.AddHandler(MouseLeftButtonUpEvent,
new RoutedEventHandler(textBox_MouseLeftButtonUp),
true);
When external control is clicked, Pop up is closed automatically, and when TextBox is clicked, Pop up is opened.
However, If Pop up is displayed, When TextBox is clicked, Pop up isn't hidden.
Anyway, I think this is enough.

How to disable opening WPF popup

I have a Popup and a ToggleButton. I set a binding like this:
<ToggleButton x:Name="myToggle" Content="{Binding MyData.Title}" />
<Popup IsOpen="{Binding IsChecked, ElementName=myToggle}" >
<TextBlock Text="{Binding MyData.Details}" />
</Popup>
As you see, I bound the toggle button's content to MyData.Title and the popup's content to MyData.Details.
Now I had the criteria MyData.ShowDetails. If it is true the popup can open and if it is false the popup should not be opened.
How can I set a binding to achieve this?
I tested these bindings on the Popup but no one works:
Visibility="{Binding MyData.ShowDetails, Converter={StaticResource BooleanToVisibilityConverter}}"
IsEnable="{Binding MyData.ShowDetails}"
You could put a panel (Grid ) on top of all the content in your window.
That needs to have a background set but it can be low opacity if you still want to see the window content.
Make that visible only when the popup is shown and collapse otherwise.
Make sure you set focus to your popup when it's shown.
.
Bear in mind.
Popups are separate windows.
They are intended to be shown briefly and have a number of potential drawbacks if you show them for longer periods. EG other applications can appear under them and they don't move with their "parent" window/control.
You might find a modal window is easier and suits better, depending on your exact requirements.
Just instantiate a window and use
PopupWindow newWindow = new PopupWindow();
newWindow.ShowDialog();
Where PopupWindow is just any old window styled to look like you want the popup.
This will guarantee the user can't somehow interact with any other window in your app.
.
Another possibility is to show your "popup" content in a grid which appears on top of everything inside your main window.
That's how editing data works in this:
https://gallery.technet.microsoft.com/scriptcenter/WPF-Entity-Framework-MVVM-78cdc204
The plus or minus of that approach is that it's in the one window.
--- Brian Kress ---
I found a special answer in my case. Instead of disabling Popup, I should disable the ToggleButton:
<ToggleButton x:Name="myToggle" Content="{Binding MyData.Title}"
IsEnabled="{Binding MyData.ShowDetails}"/>
<Popup IsOpen="{Binding IsChecked, ElementName=myToggle}" >
<TextBlock Text="{Binding MyData.Details}" />
</Popup>
It works perfect!
Note: This is not a general answer for Popup. Welcome to anyone who has an answer.

Flyout - WPF (mahApps)

I'm trying to close a flyout when a click on his or on another side of the window, I use the ExternalCloseButton=Left property. Is this okay? I also tried removing the property AutoCloseEnabled, but could not get results.
When I use a flyout with the property EnabledAutoClose, when closed, the focus is lost in the control it was.
You can help solve this problem?
<mahApps:MetroWindow.Flyouts>
<mahApps:FlyoutsControl>
<mahApps:Flyout Position="Bottom"
AutoCloseInterval="3000"
IsOpen="{Binding IsOpen}"
IsAutoCloseEnabled="True"
ExternalCloseButton="Left">
</mahApps:Flyout>
</mahApps:FlyoutsControl>
</mahApps:MetroWindow.Flyouts>
If you set IsPinned="False" then the Flyout will be closed on left mouse click outside the Flyout.
<Controls:Flyout Height="75"
CloseButtonVisibility="Collapsed"
IsPinned="False"
Position="Bottom"
TitleVisibility="Collapsed">
<TextBlock VerticalAlignment="Center" Text="This is an AppBar" />
</Controls:Flyout>
Sample is from the main demo. Hope this helps.
You can use PreviewMouseLeftButtonUp of the MainWindow or whatever view contains the flyout and set the isOpen to false. If you want to close it only when user clicks the outside of the flyout than you can check it with isMouseOver property of the flyout.

win10 UWP OnScreen Keyboard is not hiding

I have created a Win 10 UWP application . in that I have a popup for which light dismissal is enabled.
<Popup x:Name="AddWebpagePopup" IsLightDismissEnabled="True" IsOpen="{Binding IsPopupOpen}" Opened="AddWebpagePopup_Opened">
<TextBox x:Name="WebpageNameTextBox" Text="{Binding WebpageUrl, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource TexBoxStyle}" KeyDown="WebpageNameTextBox_KeyDown" />`
<Button Content="Cancel" Command="{Binding CancelCommand}" HorizontalContentAlignment="Center"/>
</popup>
In AddWebpagePopup_Opened I am just setting the focus to WebpageNameTextBox. In CancelCommandI am just setting IsPopupOpen to False
My issue is with OnScreenKeyBoard In tablet mode. Keyboard is showing properly when the popup is opened and closing when cancel button is clicked. Issue is there only when I touch outside the popup. Popup was dismissed but the keyboard was still visible. Anyone have idea why this happen?
When someone presses the "Cancel" button, the button gets focus -> the keyboard hides. It seems that the closing of popup is not enough to lose focus, so the keyboard is still visible.
You can try to change the focus when the popup is being closed. Although there is no closing event, you can register to property changed callback event.
this.AddWebpagePopup.RegisterPropertyChangedCallback(Popup.IsOpenProperty, (d, e) =>
{
if (!this.popup.IsOpen)
{
// change focus to something else
}
});

Popup with "StaysOpen=false" steals LeftMouseButtonDown event

In my application, when a user attempts to click a slider which is on the main window, while a popup control is open, the popup control steals the mouse down event.
This results in the slider not responding to the mouse down event correctly.
(it seems to get focus and move to an incorrect location)
I found that the that the "OnPreviewMouseLeftButtonDown" in the slider does not fire when popup's "StaysOpen" property is false (and the popup is open),
and does fire when its true (or when the popup is closed).
I was wondering if someone has found a solution for this issue.
I encountered these type of issues in other controls in my application in various contexts, So I would prefer a more general solution rather than just solving this for the slider.
Sample code:
<Window x:Class="SampleApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="Root"
Title="MainWindow" Height="350" Width="525">
<Grid Height="130" Width="300">
<Button Width="40" Height="40" Click="ButtonBase_OnClick" HorizontalAlignment="Left" VerticalAlignment="Top"></Button>
<Popup StaysOpen="False" IsOpen="{Binding ElementName=Root, Path=IsOpen}" Width="100" Height="100"
HorizontalAlignment="Center" VerticalAlignment="Center" Placement="Center">
<Grid Background="Black">
<TextBlock Text="hello"></TextBlock>
</Grid>
</Popup>
<Slider Width="200" IsMoveToPointEnabled="True" VerticalAlignment="Bottom"></Slider>
</Grid>
Thanks ahead,
Yotam
This happens because PreviewMouseDown (and it's derivates) (from the base class UIElement) has a default RoutingStrategy.Direct.
Direct - The routed event does not route through an element tree, but does support other routed event capabilities such as class handling, EventTrigger or EventSetter.
This is the source code of the event taken from ReferenceSource.
public static readonly RoutedEvent PreviewMouseLeftButtonDownEvent =
EventManager.RegisterRoutedEvent(
"PreviewMouseLeftButtonDown",
RoutingStrategy.Direct,
typeof(MouseButtonEventHandler),
_typeofThis);
And here is what happens in the Popup:
private void OnPreviewMouseButton(MouseButtonEventArgs e)
{
// We should only react to mouse buttons if we are in an auto close mode (where we have capture)
if (_cacheValid[(int)CacheBits.CaptureEngaged] && !StaysOpen)
{
Debug.Assert( Mouse.Captured == _popupRoot.Value, "_cacheValid[(int)CacheBits.CaptureEngaged] == true but Mouse.Captured != _popupRoot");
// If we got a mouse press/release and the mouse isn't on the popup (popup root), dismiss.
// When captured to subtree, source will be the captured element for events outside the popup.
if (_popupRoot.Value != null && e.OriginalSource == _popupRoot.Value)
{
// When we have capture we will get all mouse button up/down messages.
// We should close if the press was outside. The MouseButtonEventArgs don't tell whether we get this
// message because we have capture or if it was legit, so we have to do a hit test.
if (_popupRoot.Value.InputHitTest(e.GetPosition(_popupRoot.Value)) == null)
{
// The hit test didn't find any element; that means the click happened outside the popup.
SetCurrentValueInternal(IsOpenProperty, BooleanBoxes.FalseBox);
}
}
}
}
So it was designed to work this way, and you should likely not use OnPreviewMouseDown for whatever you are trying to accomplish here.
In my application, when a user attempts to click a slider which is on the main window, while a popup control is open, the popup control steals the mouse down event
While your description is not completely correct, that is the normal behaviour of any Popup control. The reason that this occurs is because the Popup control has focus and so it is listening out for the Click event even if it occurs outside the bounds of the Popup. Think about this logically now... if it didn't do this, how would it know when to close? You will find the same behaviour from the Popup control used in a ComboBox.
There is a workaround to achieve the behavior you require, Set 'IsHitTestVisible = True' for the Slider control you are use.
PS:
Set IsHitTestVisible = True, only when the Popup is Open - False otherwise.

Categories

Resources