I have a simple ContentDialog with ContentDialog.XAML:
<ContentDialog x:Class="SampleApp.Dialogs"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:SampleApp.Dialog"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
PrimaryButtonClick="OkClick"
PrimaryButtonText="OK"
SecondaryButtonText="Cancel"
SecondaryButtonClick="CancelClick"
mc:Ignorable="d">
<StackPanel>
<TextBox
Text="{x:Bind NameOne, Mode=TwoWay}" />
<TextBox Text="{x:Bind NameTwo, Mode=TwoWay}" />
</StackPanel>
In the code-behind:
private void OkClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
{
this.Hide();
}
When I want to initalize this Dialog by:
Dialog dialog = new Dialog();
var result = await dialog.ShowAsync();
The resultis always of type ContentDialogResult.None. Even if I click "Ok" or "Cancel", but it should be at least ContentDialogResult.Primary when I click "Ok". It this an expected behavior?
The issue was the PrimaryButtonClick="OkClick" , OkClick overriding the default action (which is hide) and therefore the result is always None.
Removing this solved the problem.
private void OkClick(object sender, RoutedEventArgs e)
{
this.Result = MyResult.Yes;
// Close the dialog
dialog.Hide();
}
Related
I have situation where I want an overlay control to block UI interactions on a Page for everything that is behind a border. I have tried setting Border.ManipulationMode to False. I have set IsTapEnabled, IsRightTapEnabled, IsDoubleTapEnabled, and IsHitTestVisible to False.
I also tried subscribing to the Tapped and PointerEntered events, and setting the args Handled property to true. After all of this I can still click on Buttons through the border, and invoke their commands. Below are a few screenshots for context:
Page with no overlay
Page now has what should be an overlay that blocks controls behind it
A button capturing PointerOver that shouldn't be
Here is the UserControl xaml that becomes the overaly on the Page:
<UserControl x:Class="PocMvvmToolkitApp.Dialogs.DialogShell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid x:Name="overlayGrid"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<!--dialogShield is the Border that I want to prevent click through on-->
<Border x:Name="dialogShield"
Background="#AAFFFFFF"
IsHitTestVisible="False"
ManipulationMode="None"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
IsDoubleTapEnabled="False"
IsHoldingEnabled="False"
IsRightTapEnabled="False"
IsTapEnabled="False"/>
<Border x:Name="dialogBorder"
BorderBrush="Black"
BorderThickness="1" />
</Grid>
Attempting to handle the events:
public DialogShell()
{
this.InitializeComponent();
this.allDialogs = new List<ExtendedContentDialog>();
this.visibleDialogs = new List<ExtendedContentDialog>();
////Doesn't work
this.dialogShield.PointerEntered += this.OnModalShieldPointerEntered;
this.dialogShield.Tapped += this.OnModalShieldTapped;
}
private void OnModalShieldTapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
{
////Doesn't block click through
e.Handled = true;
}
private void OnModalShieldPointerEntered(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
{
e.Handled = true;
}
On the Page.xaml.cs here is where I add or remove the DialogShell control to the parent Grid on the page:
private void OnDialogStackChanged(Args.DialogStackChangedEventArgs args)
{
switch (args.Context)
{
case Args.DialogStackChangedContext.Showing:
if (this.dialogShell == null)
{
this.dialogShell = new DialogShell();
this.dialogShell.ShowDialog(args.Dialog);
this.rootGrid.Children.Add(this.dialogShell);
Grid.SetColumnSpan(this.dialogShell, 2);
}
break;
case Args.DialogStackChangedContext.Closing:
if (this.dialogShell != null)
{
this.dialogShell.RemoveDialog(args.Dialog);
if (this.dialogShell.AllDialogs.Count == 0)
{
this.rootGrid.Children.Remove(this.dialogShell);
this.dialogShell = null;
}
}
break;
}
}
Any help with this Border situation would be appreciated. Before someone recommends using ContentDialog, please don't, I have my reasons for this setup. Thanks!
I am using MaterialDesign for my WPF project which downloads json from remote server and parse.
Before showing MainWindow, I want to open initial loading dialog to show how much loading is completed.
MainWindow.xaml
<materialDesign:DialogHost Identifier="RootDialog" CloseOnClickAway="False">
<TextBlock Text="Loading Completed." />
</materialDesign:DialogHost>
MainWindowViewModel.cs
public class MainWindowViewModel: BaseViewModel
{
public MainWindowViewModel(Window mWindow) {
...
ShowInitialDialog();
...
}
private async void ShowInitialDialog()
{
var view = new LoadingDialog();
//show the dialog
var result = await DialogHost.Show(view, "RootDialog", null, null);
//check the result...
Debug.WriteLine("Dialog was closed, the CommandParameter used to close it was: " + (result ?? "NULL"));
}
}
LoadingDialog.xaml
<UserControl 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"
xmlns:wpf="clr-namespace:MaterialDesignThemes.Wpf;assembly=MaterialDesignThemes.Wpf"
mc:Ignorable="d">
<StackPanel Orientation="Vertical" VerticalAlignment="Center" Margin="10">
<ProgressBar Width="60" Height="60" Margin="16"
Style="{DynamicResource MaterialDesignCircularProgressBar}"
IsIndeterminate="True"
Value="33"/>
<TextBlock Text="{Binding Notification}" HorizontalAlignment="Center"></TextBlock>
</StackPanel>
</UserControl>
But when I ran the code, it shows error "DialogHost Instance not exist".
How do I get to know when the "RootDialog" DialogHost is instatiated?
Wait intil the DialogHost instance in the window has been loaded:
public class MainWindowViewModel : BaseViewModel
{
public MainWindowViewModel(Window mWindow)
{
mWindow.rootDialog.Loaded += (s, e) => ShowInitialDialog();
}
private async void ShowInitialDialog()
{
var view = new LoadingDialog();
//show the dialog
var result = await DialogHost.Show(view, "RootDialog", null, null);
//check the result...
Debug.WriteLine("Dialog was closed, the CommandParameter used to close it was: " + (result ?? "NULL"));
}
}
XAML:
<materialDesign:DialogHost x:Name="rootDialog" x:FieldModifier="internal"
Identifier="RootDialog" />
As a side note, a view model having a strong reference to a window breaks the MVVM pattern.
I am displaying a modal dialog when the user double taps inside a TextBlock. Its a backdoor to a hidden settings panel. The TextBlock is contained in a Popup. I am finding that it is always necessary to tap/touch once before any of the buttons in the dialog do anything. Kind of annoying. Initially was using MouseLeftButtonDown and ClickCount==2 on the TextBlock but have also tried the DoubleClickEvent of a Label and their Preview... versions. Nothing I have tried fixes this problem.
<TextBlock Foreground="Black" FontSize="16" Grid.ColumnSpan="4" HorizontalAlignment="Center" MouseLeftButtonDown="TextBlock_MouseLeftButtonDown" VerticalAlignment="Center" Padding="0,10,0,10">
<Run Text="{x:Static languages:Strings.SoftwareVersion}"/>
<Run Text="{Binding SoftwareBuild}"/>
<Run Text=" "/>
<Run Text="{x:Static languages:Strings.FirmwareVersion}"/>
<Run Text="{Binding FirmwareBuild}"/>
</TextBlock>
private void TextBlock_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
try
{
if (e.ClickCount == 2)
{
var sw = new SettingsWindow();
sw.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
sw.DataContext = this.DataContext;
sw.ShowDialog();
}
}
catch (Exception ex)
{
ex.HandleException();
}
}
I've made a correction to the title as the problem is only with touch/tap behaviour; the first mouse click does get through only the first touch fails.
Added more code for the SettingsWindow as requested:-
<Window x:Class="XXXXXXX.UserInterface.Views.Miscellaneous.SettingsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="SettingsWindow" Height="150" Width="200">
<Grid>
<Button Content="Click Me" Click="Button_Click" VerticalAlignment="Center" HorizontalAlignment="Center" Height="48" Margin="50,30,37,41" Width="105" />
</Grid>
</Window>
public partial class SettingsWindow : Window
{
public SettingsWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
(sender as Button).Background = new SolidColorBrush(Colors.Red);
(sender as Button).Content = "WAS CLICKED";
}
}
Ive tried focus setting in the load and activate event of the dialog to no avail. Even tried raising a MouseClick event using RaiseEvent.
Same problem if I only count 1 click too but with 1 click the problem goes away if I count MouseButtonUp events not MouseButtonDown, but then I lose the ClickCount==2 option which doesnt work at all. Somewhere a MouseButtonUp event is getting lost.
So I'm about to manage my own double clicking to get this to work ...
but suggestions welcome as to why this breaks.
Jerry
I created a new WPF app in Visual Studio and I placed a button using the drag and drop editor but I can't access the button in my .cs file using
MainButton.Content = "Set output to red";
but I get an error
System.NullReferenceException: 'Object reference not set to an instance of an object.'
MainButton was null while running the application.
The drag and drop editor generated this xaml file
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Border HorizontalAlignment="Center" VerticalAlignment="Center" BorderBrush="Black" BorderThickness="3">
<TextBlock x:Name="Output" Background="Transparent" TextAlignment="Center" TextWrapping="Wrap" Text="Output" Height="88" Width="264"/>
</Border>
<RadioButton x:Name="Option1" Content="Red Pill" HorizontalAlignment="Left" Margin="135,75,0,0" VerticalAlignment="Top" Checked="RadioButton_Checked" IsChecked="True"/>
<RadioButton x:Name="Option2" Content="Blue Pill" HorizontalAlignment="Left" Margin="536,72,0,0" VerticalAlignment="Top" Checked="RadioButton_Checked_1"/>
<Button x:Name="MainButton" Content="Set output to red" HorizontalAlignment="Left" Margin="279,100,0,0" VerticalAlignment="Top" Width="213" Height="41" Click="MainButton_Click"/>
</Grid>
</Window>
Here's the .cs file
using System.Windows;
using System.Windows.Media;
namespace WpfApp1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void MainButton_Click(object sender, RoutedEventArgs e)
{
if ((bool)Option1.IsChecked)
{
Output.Background = Brushes.Crimson;
}
else
{
Option2.IsChecked = true;
Output.Background = Brushes.DodgerBlue;
}
}
private void RadioButton_Checked(object sender, RoutedEventArgs e)
{
MainButton.Content = "Set output to red";
}
private void RadioButton_Checked_1(object sender, RoutedEventArgs e)
{
MainButton.Content = "Set output to blue";
}
}
}
I can access other things in the UI just fine like radio buttons and text blocks but not the button. Why could this be happening?
During the initialization phase, some variables are going to be null since it hasn't been reached in the call order. RadioButton_Checked is called through event before the button is constructed since it contains the Checked property.
A quick and easy fix is as follows: Check for null in your event calls.
private void RadioButton_Checked (object sender, RoutedEventArgs e)
{
if(MainButton != null)
MainButton.Content = "Set output to red";
}
private void RadioButton_Checked_1 (object sender, RoutedEventArgs e)
{
if (MainButton != null)
MainButton.Content = "Set output to blue";
}
Of course, there are better ways to handle this. You could set checked on a separate event, Initialized, which will handle it much cleaner.
I created a pop-up and want to show it when a button has been clicked. But it doesn't work because it waits for finishing button's duty.
I don't want to use "timer, thread and background worker" because I already can do it with that. I am looking for an another solution…
Here is my code:
void btnSearch_Click(object sender, RoutedEventArgs e)
{
LoadingOpen();
if (cmbvideoserver.Text == "Youtube")
SearchInYoutube();
else if (cmbvideoserver.Text == "Vimeo")
SearchInVimeo();
LoadingClose();
}
public void LoadingOpen()
{
myPopup.IsOpen = true;
Common.Popup = true;
window.Opacity = 0.3;
}
public void LoadingClose()
{
myPopup.IsOpen = false;
Common.Popup = false;
window.Opacity = 1;
}
and the XAML:
<Window Name="window" x:Class="youtube.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" Loaded="window_Loaded">
<Canvas Name="main">
<Popup Name="myPopup" IsOpen="False" PopupAnimation="Slide"
Margin="100,10,20,0" Placement="Center" >
<Label Content="Loading..."></Label>
</Popup>
</Canvas>
</Window>
How can I show popup on my main window ? (without any thread,timer and background controls/classes)
You can show Windows as dialogs by useing the ShowDialog() method.