Flyout - WPF (mahApps) - c#

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.

Related

Place a popup under a button (UWP, XAML, C#)

I have created a Button. When the button is pressed a Popup appears. The Problem is, the popup is on the top left side while the button is on the Right side.
What do I have to do in XAML to make the popup appear under the button?
I even tried to place the popup in the top rightcorner via HorizontalAllignment. The Problem then is that the popup is outside my program (Right next to it. Literally).
just use the new DropDownButton in the new winUi library, it has a build in popup which comes under the button and the button even has an arrow on right side, it is perfect for your scenario. just use the nuget package, docs are here : https://learn.microsoft.com/en-us/uwp/toolkits/winui/
You can use the Flyout which is attached to specific controls including Button, then You can use the Placement property to specify where a flyout appears: Top, Left, Bottom, Right, or Full. So you can use the Placement property to specify the flyout to appear under the button as the following code.
<Button Content="Click me">
<Button.Flyout>
<Flyout Placement="Bottom">
<TextBlock Text="This is a flyout!"/>
</Flyout>
</Button.Flyout>
</Button>
By the way, as we suggestion in the Remark part,
Do not use a Popup if a Flyout, MenuFlyout, ToolTip or ContentDialog (MessageDialog for a Windows 8 app) is more appropriate.

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.

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.

Set Focusable=False cause TabItem not selectable in wpf

In a window I have some TextBoxes and a TabControl and I want only textboxes be selectable.
I set Focusable=False in TabItem. But this made TabItem not selectable. How can I fix this problem.
What I understood from your description is that you want to change focus using "Tab" key and you don't want TabControl to be selected.
For that instead of setting Focusable=false, set IsTabStop="False".
<TabItem IsTabStop="False" Header="Item 1">Content1</TabItem>
Setting IsTabStop="False" will ignore that control while changing focus using Tab key.
Hope this will solve your issue.

Attach a single close button on the tabcontrol in C#

How i can attach a single close button on the tabcontrol in C#.
There is a many way to attach a close button individually on each tabpages but I want to attach only single(e.g.) we can see on microsoft visual stdio 2008.
So Plz help me.
Here is a cheap way to do it, which might get you started:
<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">
<DockPanel>
<TabControl DockPanel.Dock="Top">
<TabItem Header="Test1" />
<TabItem Header="Test2" />
<TabItem Header="Test3" />
<TabItem Focusable="False">
<TabItem.Header>
<Button Command="{Binding CloseTab}" Content="X" Width="21" HorizontalAlignment="Stretch" />
</TabItem.Header>
</TabItem>
</TabControl>
</DockPanel>
</Window>
You then are left to implement a public ICommand CloseTab field or property on your DataContext, and style the tab control to your liking.
Edit:
If you use this method:
Wiring up the button is tricky. You have to be careful not to close the tab that contains the button
This isn't well adapted to dynamically created tabs, because you have to ensure the close button is appended to the list
You have to figure out how to re-select the last selected tab, when you close the selected tab
You'll also have weird behavior when tabs start to wrap
The tab-stop behavior is hard to get right. You can't make the last TabItem focusable, since focus is used to determine what to close, but tabbing to the close button breaks the normal TabItem keyboard flow
I have come up with a style that makes the button look like a regular tab, with a bold X on it, which makes it visually more like IE8, and fixes the keyboard selection problem. But it is complicated, and this solution is complicated enough.
Ultimately, a close button on every tab jives better with the tab control's default behavior. The only problem with that solution is that it takes up more space. You could cheat and make the close button collapse until you mouse over the tab item, though that's sort of a user-experience no-no, unless you just shrink it.
If you are serious about following through with the separate close button, I suggest you look at this article, and adapt what they do for the scroll buttons to your close button:
http://www.blogs.intuidev.com/post/2010/02/10/TabControlStyling_PartThree.aspx
Ignore what they do for close buttons :)
Would it be possible to have your tabcontrol on another container control and let that control's close button do the job?

Categories

Resources