UWP - Close my content dialog on click on the blank area - xaml

I have created a content dialog for my UWP app which involves a centralized UI Element and a surrounding blank area.But content dialog does not have a property like "IsLightDismissEnabled" to close the dialog on click on an area except the UIELEMENT area.How can I achieve it?

In the code behind your content dialog:
public sealed partial class CustomDialog : ContentDialog
{
public CustomDialog()
{
this.InitializeComponent();
Boolean isHide;
Window.Current.CoreWindow.PointerPressed += (s, e) =>
{
if (isHide)
Hide();
};
PointerExited += (s, e) => isHide = true;
PointerEntered += (s, e) => isHide = false;
}
}

There are few options that I can think of:
Use popup (like uruk suggested) and add your controls inside, create the popup at desired location (you could also use binding here if you want to show the popup at location depending on user input at runtime Popup has HorizontalOffset and VerticalOffset properties)
Create a parent view that is taking up the whole page but is transparent, then add your UI elements at the center and attach tap/click events to the transparent view. These events are going to just close remove/collapse the transparent view which contains the other elements inside (Either by binding of values or by setting the values to the UI elements).
Example or popup usage:
<Popup x:Name="MenuPopUp"
IsLightDismissEnabled="True"
HorizontalOffset="{Binding HorizontalOffset}"
VerticalOffset="{Binding VerticalOffset}"
IsOpen="{Binding IsOpen, Mode=TwoWay}">
<Grid>
YOUR ELEMENTS HERE
</Grid>
</Popup>

Content dialog is a modal dialog. Why don't you use a Popup or a child class of it? It's non-modal, and it already has the IsLightDismissEnabled property you just mentioned.

<Popup x:Name="MenuPopUp"
IsLightDismissEnabled="True"
LostFocus="MenuPopUp_LostFocus"/>
In CS
private void MenuPopUp_LostFocus(object sender, RoutedEventArgs e)
{
MenuPopup.IsOpen = false;
}

Related

I'm trying to go to another page when clicking a button. How could i do this (WinUI 3)

I'm trying to go to another page when clicking a button. How could i do this.
I tried using a NavigationViewItem but it didn't work.
The NavigationViewItem you posted is used in UWP.
If it is a WinUI3 project, then you need to refer to this document, use Navigate.
the relevant code samples are as follows.
xaml
<Button x:Name="myButton" Click="myButton_Click"/>
xaml.cs
private void myButton_Click(object sender, RoutedEventArgs e)
{
Frame rootFrame = new Frame();
this.Content = rootFrame;
rootFrame.Navigate(typeof(BlankPage1), null);
}

How to close ComboBox list items when moving application window of my WinRT/C++ UWP application?

I have a pair of ComboBox controls having IsEditable() true as well as false.
When I am scrolling through my application or moving my application window (by clicking on the title bar) with list popup open, I would like to close the ComboBox list popup as otherwise there would be a weird delay in aligning the list correctly below the control.
Is this possible in UWP with WinRT/C++? If so, kindly suggest how to.
I did an investigation to find if any events are there to handle in such a scenario when ComboBox control is essentially displaced from initial position while moving the app window/scrolling the app, but couldn't find any help.
Edit: Adding ComboBox image from XAML Controls Gallery to demonstrate the behaviour. In case if IsEditable set as true, when popup is opened and application is scrolled then popup goes outside the window. Instead I would like to dismiss the popup itself. However, if IsEditable is set as false then we cannot scroll until the popup is dismissed.
Update: The code I tested for PointerWheelChanged
void CBFile2022X::OnPointerWheelChangedHandler( Windows::Foundation::IInspectable const& sender,
Windows::UI::Xaml::Input::PointerRoutedEventArgs const& eventargs )
{
OutputDebugString( L"PointerWheelChanged" );
if( ComboBox != nullptr )
{
ComboBox.IsEnabled( false );
ComboBox.IsEnabled( true );
}
}
I have to say that currently there is no event to detect if the application window is moved or changed its location.
Update:
You could handle the UIElement.PointerWheelChanged Event which will be fired when users scroll the mouse wheel. You could set the IsEnabled property of the ComboBox to false first and then set it to true, this will make the ComboBox lose its focus. Like:
private void Mypanel_PointerWheelChanged(object sender, PointerRoutedEventArgs e)
{
FontsCombo.IsEnabled = false;
FontsCombo.IsEnabled = true;
}
Update2:
If you are using a ScrollViewer you could try to handle the ScrollViewer.ViewChanging Event.
private void ScrollViewer_ViewChanging(object sender, ScrollViewerViewChangingEventArgs e)
{
FontsCombo.IsEnabled = false;
FontsCombo.IsEnabled = true;
}

What element to use if I only need an placement target element

I want to show a flyout at a specific place. I want to specify a placement target element in XAML, but I want to make sure I am using the "lightest" element possible, given that I don't want that element to ever be visible or interacted with.
Is there a "recommended" or "correct" element to use? If not, what would be the "lightest" element to use? Or am I overthinking this and should just use a button?
I want to show a flyout at a specific place.
The place of FrameworkElements are based on the panel that you are using to hold them. If you want to show your flyout based on a FrameworkElement being placed in a specific place, you can use Canvas to position your FrameworkElement.
I want to specify a placement target element in XAML, but I want to make sure I am using the "lightest" element possible.
Flyout.ShowAt takes FrameworkElement as it's placement target. So I think the "lightest" element would be an empty custom FrameworkElement like below:
public class MyElement:FrameworkElement
{
}
And you can put it into XAML and use Canvas to position it:
<Page
x:Class="PopupSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:PopupSample"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Canvas>
<Button Name="btnClick" Canvas.Left="50" Canvas.Top="500" Click="btnClick_Click">Click Me</Button>
<local:MyElement x:Name="myEle" Canvas.Left="100" Canvas.Top="100"></local:MyElement>
</Canvas>
Code-Behind:
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private void btnClick_Click(object sender, RoutedEventArgs e)
{
Flyout flyout = new Flyout();
TextBlock tbContent = new TextBlock
{
Text= "this is a flyout content"
};
flyout.Content = tbContent;
flyout.ShowAt(myEle);
}
}
Grid is a pretty light element, it's just a simple Panel-derived class without any child elements. Button is a Control, meaning it has a template which will create many child elements that make up its visual appearance.
Are you saying you want to use a dummy element just for the purpose of specifying the position of the flyout which you will show programmatically? If you want to avoid the element altogether, then maybe a Popup would be a better choice.

UWP Light dismiss ContentDialog

Is there a way to make the ContentDialog light dismiss?, so when the user clicks on any thing outside the ContentDialog it should be closed.
Thanks.
By default, ContentDialog is placed in PopupRoot. Behind it, there is a Rectangle which dim and prevent interaction with other elements in the app. You can find it with help of VisualTreeHelper and register a Tapped event to it, so when it's tapped you can hide ContentDialog.
You can do this after calling ShowAsync outside ContentDialog code or you can do it inside ContentDialog code. Personally, I implement a class which derives from ContentElement and I override OnApplyTemplate like this:
protected override void OnApplyTemplate()
{
// this is here by default
base.OnApplyTemplate();
// get all open popups
// normally there are 2 popups, one for your ContentDialog and one for Rectangle
var popups = VisualTreeHelper.GetOpenPopups(Window.Current);
foreach (var popup in popups)
{
if (popup.Child is Rectangle)
{
// I store a refrence to Rectangle to be able to unregester event handler later
_lockRectangle = popup.Child as Rectangle;
_lockRectangle.Tapped += OnLockRectangleTapped;
}
}
}
and in OnLockRectangleTapped:
private void OnLockRectangleTapped(object sender, TappedRoutedEventArgs e)
{
this.Hide();
_lockRectangle.Tapped -= OnLockRectangleTapped;
}
Unfortunately ContentDialog does not offer such behavior.
There are two alternatives you can consider:
Popup - a special control built for this purpose, which displays dialog-like UI on top of the app content. This control actually offers a IsLightDismissEnabled for the behavior you need. Since the Anniversary Update (SDK version 1607) also has a LightDismissOverlayMode, which can be set to "On" to automatically darken the UI around the Popup when displayed. More details are on MSDN.
Custom UI - you can create a new layer on top of your existing UI in XAML, have this layer cover the entire screen and watch for the Tapped event to dismiss it when displayed. This is more cumbersome, but you have a little more control over how it is displayed

How to disable right-button selection on List View Item (ListViewItem)?

I want to prevent the ability to deselect a list view item if it is already selected. Therefore how do I prevent right mouse click ability to deselect an item?
I have prevented the ability to deselect via swiping by using IsSwipeEnabled="False" on the List View. I didn't require swipe ability on the list view.
I'm happy to completely prevent right mouse click on the list view items if needed.
If I am reading your question correctly, it sounds like you want the ability for the user to select items, but to not be able to de-select. If that is the case, it seems like a strange requirement - it goes against normal UI convention and does something that the user is not expecting.
Having said that, you can do so by handling the SelectionChanged event in the ListView.
When the event is triggered, it gives you a list of removed (de-selected) items. You then just need to add those items back into the ListView's selected items list:
private void itemListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
foreach (var item in e.RemovedItems)
{
itemListView.SelectedItems.Add(item);
}
}
Note that if you use the above code, you do not have to handle any swipe or mouse events.
Edit - Per OP's comment, the requirement is slightly different than what I thought:
I want the selected item to deselect if a different item is selected. however what I dont want is an already selected item to be (manually) deselected
Assuming that you have a single select ListView, you can still use the SelectionChanged event and the SelectionChangedEventArgs to do what you are asking for:
private void itemListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.RemovedItems.Count > 0 && e.AddedItems.Count == 0)
{
var removed = e.RemovedItems[0];
itemListView.SelectedItem = removed;
}
}
I have found a simple solution on the following forum.
You simply add a RightTapped event to the ListView DataTemplate content.
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<ContentPresenter RightTapped="daves_RightTapped" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
And then in the code behind:
private void daves_RightTapped(object sender, Windows.UI.Xaml.Input.RightTappedRoutedEventArgs e)
{
e.Handled = true;
}
This works fine on an outlook style ListView.