I have a little problem when opening a window by ShowDialog.
I have a main window which when the application is loading data from the data source, opens another small window as a dialog to show the loading progress.
When the small loading progress window opens up, the cursor of that window is set to a custom Busy cursor and I am trying to set the main window's cursor to be the same as in the small loading window, but no matter what I try, it doesn't work.
I know that when opening a window as a dialog with ShowDialog, the opening window's cursor is set to be the normal default cursor (when hovering over your dialog, you have your selected cursor, but when hovering over the main window while the dialog is open, the cursor is set to the default cursor [arrow]).
I am trying to make my app show the same custom Busy cursor when the loading dialog is open, while hovering over the dialog itself and over the window that has opened the dialog, while preventing the user from accessing the main window's content, preventing from minimizing the small loading window and preventing from letting the small loading window be under the main window.
Is there any way of doing so (as stated above) while using ShowDialog or something similar to ShowDialog?
Is there way of changing the default cursor of the ENTIRE application (for example a custom arrow cursor instead of the one windows has by default)?
Is there any way of opening a dialog, setting it's cursor to be a custom Busy cursor and by that setting that cursor to be present while hovering over any part of the application?
My codes:
private void Window_ContentRendered(object sender, EventArgs e)
{
Mouse.OverrideCursor = new Cursor(System.IO.Path.GetFullPath(System.IO.Path.Combine(strCurrentDir, #"..\..\")) + #"Cursors\busy.ani");
//this.Cursor = new Cursor(System.IO.Path.GetFullPath(System.IO.Path.Combine(strCurrentDir, #"..\..\")) + #"Cursors\busy.ani");
//Mouse.OverrideCursor = Cursors.Wait;
bwReload = new BackgroundWorker();
bwReload.WorkerReportsProgress = true;
bwReload.DoWork += (sender_bw, e_bw) =>
{
new Thread(() =>
{
Application.Current.Dispatcher.Invoke(() =>
{
ProgressBarWindow pbwLoadWindow = new ProgressBarWindow("Loading...", this);
pbwLoadWindow.ShowInTaskbar = false;
pbwLoadWindow.Owner = this;
pbwLoadWindow.Cursor = new Cursor(System.IO.Path.GetFullPath(System.IO.Path.Combine(strCurrentDir, #"..\..\")) + #"Cursors\busy.ani");
pbwLoadWindow.ShowDialog();
});
}).Start();
ReloadA();
ReloadB();
};
bwReload.RunWorkerCompleted += (sender_bw, e_bw) => btnViewDashboard_Click(this, null);
bwReload.RunWorkerAsync();
}
Thanks in advance.
SOLVED
It is simple.
All you need to do is go to the dialog window's xaml and fit the window like that, that it will cover the entire main window.
Code:
<Window x:Class="PlGui.ProgressBarWindow"
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:PlGui"
mc:Ignorable="d" Height="600" Width="1025"
ResizeMode="NoResize" WindowStartupLocation="CenterScreen"
WindowStyle="None" AllowsTransparency="True">
<Window.Background>
<SolidColorBrush Opacity="0.01" Color="White"/>
</Window.Background>
<Grid Height="100"
Width="350"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="#7f8c8d">
......
</Grid>
</Window>
The results:
Related
I've built a dialog window that i plan to use in my whole application instead of using a message box. Whenever i need to use it, i would call it in the code behind of my Window i'm currently working with this syntax:
public void ShowDialogWindow(object sender, DialogEventArgs e)
{
DialogWindow dialog = new DialogWindow(e.MessageToShow, DialogType.Error, ButtonsType.OkOnly, this.ActualWidth, this.ActualHeight, this);
dialog.ShowDialog();
}
this is the constructor of my Dialog Window
public DialogWindow(string messageToDisplay, DialogType dialog, ButtonsType buttons, double width, double height, object Owner)
{
InitializeComponent();
this.DataContext = this;
this.Owner = Owner as Window;
AWidth = width;
AHeight = height;
-----
}
and this is the opening Window tag in the xaml
<Window x:Class="DialogWindow"
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" WindowStyle="None"
WindowStartupLocation="CenterOwner"
AllowsTransparency="True"
Width="{Binding AWidth}" Height="{Binding AHeight}"
MinHeight="720" MinWidth="1080">
Now my problem is. When i call this dialog when the owner is Minimized (having set MinWidth = 1080 and MinHeght = 720) the dialog "kinda" fits (ActualWidth and Actual Height of both Window and DialogWindow are the same, but visually the DialogWindow seems a little bit bigger than the Owner)
But when i go full screen it happens this:
Not only the ActualHeight is different to the property AHeight (which is set correctly to the ActualHeight of the Owner), but also is not centered on the Owner window at all, but overflow on my second screen. What cause this, and how can i solve it?
So i'm going to post what it solved my problem, but i have absolutely no idea why that happened, so if anyone has a better answer i will check that as accepted.
To solve my problems i removed the binding for width and height and simply added in the constructor of the DialogWindow
this.Width = OwnerActualWidth;
this.Height = OwnerActualHeight;
since i am passing those parameter in input
I have a window, it will do some checking before it is shown.
public class MyDlg : Window
{
public MyDlg()
{
Initialized += new EventHandler(Window_Initialized);
}
private void Window_Initialized(object sender, EventArgs eventArgs)
{
if (!/*do some checking*/)
{
Loaded += (s, e) => Close();
}
}
}
If "do some checking" fail, the above code will close my window immediately after the window is loaded. However this is too late because I can see the window just appear and disappear.
How can I close my window without showing it?
EDIT:
The one who will construct MyDlg is like:
MyDlg dlg = new MyDlg ();
dlg.ShowDialog();
But it is hard for me to prevent calling 'ShowDialog()', because they are written by other people (I'm trying to write MyDlg in some library)
How can I close my window without showing it?
Perform the check before calling the Show or ShowDialog method of the window. You could either do this in the calling code:
MyDlg dlg = new MyDlg();
//perform your check here...
dlg.ShowDialog();
...or in the constructor of the MyDlg window:
public MyDlg()
{
//perform your check here...
}
Obviously the window is already shown by the time the Window_Initialized event handler gets invoked so then it is too late to perform any check if you don't want the window to appear. You cannot close a window that hasn't been opened.
You can create splash dialog inside your new window.
And set IsEnabled=False on window/dialog.
Or if your operation is quick then there is no need for splash. Just hide your window:
<Window x:Class="Wpf.Test01.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:Wpf.Test01"
xmlns:charting="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit"
mc:Ignorable="d"
IsEnabled="False"
WindowStyle="None"
AllowsTransparency="True"
Title="MainWindow" Height="350" Width="525">
<Window.Background>
<SolidColorBrush Opacity="0.0" Color="White" />
</Window.Background>
You can see it done here WPF Window with transparent background containing opaque controls
Of course change the properties back to visible/default if everything is ok
In my app, I'm loading a DocumentViewer for previewing and printing. Because loading can take up to a few seconds, I would like to display a ProgressDialog. The logic is this: display ProgressDialog, create and display DocumentViewer, close ProgressDialog.
The problem is that when closing the dialog, the focus returns to the MainWindow, instead of remaining to the DocumentViewer window. I think it's because the dialog CloseAsync(). I've tried calling Focus(), Activate(), Show(), setting TopMost = true, setting the owner of the child window, but, although the window is displayed in front of the parent, the focus still returns to the parent. The only way to I restored the focus to the child was by doing a programmatic click inside the child window, in ProgressDialogController.Closed event, but the disadvantage is that there is an ugly transition (child initially appears in front, then parent, then child again).
Can CloseAsync() be avoided? Or how to close MahApps ProgressDialog without losing focus on child control?
UPDATE
I'm using MahApps 1.3.0.157. The code I'm using in Viewmodel:
public async void PrintLogExecute()
{
await DialogService.ShowProgressDialog(Properties.Resources.loading_message_box_title, Properties.Resources.loading_message_box_text);
ReportingClass.PrintDataGrid(LogEntries);
DialogService.CloseProgressDialog();
}
The DialogService class:
static class DialogService
{
public static async Task ShowProgressDialog(string dialogTitle, string message)
{
var metroWindow = (GetMainWindow() as MetroWindow);
controller = await metroWindow.ShowProgressAsync(dialogTitle, message);
controller.SetIndeterminate();
}
public static void CloseProgressDialog()
{
controller.CloseAsync();
}
private static Window GetMainWindow()
{
return Application.Current.Windows[0];
}
}
When executing PrintLogExecute(), the document previewer firstly appears in front of the main window and immediately after this, when executing DialogService.CloseProgressDialog() it goes to background. Like I said, the only way I restored the focus to the child was by doing a programmatic click inside the child window, in ProgressDialogController.Closed event.
maybe this helps you.
<mahApps:MetroWindow x:Class="WakeOnLanV2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:commands="clr-namespace:WakeOnLanV2.Commands"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:mahApps="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:viewModels="clr-namespace:WakeOnLanV2.ViewModels"
xmlns:views="clr-namespace:WakeOnLanV2.Views"
xmlns:wakeOnLan="clr-namespace:WakeOnLanV2"
x:Name="MainView" >
<Grid>
<Grid>
<!-- main grid -->
</Grid>
<mahApps:ProgressRing Width="150"
Height="150"
Canvas.ZIndex="110"
IsActive="{Binding Path=IsBusy,
UpdateSourceTrigger=PropertyChanged,
FallbackValue=False}"
IsLarge="True" />
</Grid>
</mahApps:MetroWindow>
The ring is under the MainGrid to keep it in the foreground.
I got the answer from GitHub:
https://github.com/MahApps/MahApps.Metro/issues/2532
I have a problem showing modal windows in my application. My application functions like a web browser in that it can host multiple windows (i.e. the same application runs in two or more windows). Due to this, I want Modal windows to only be modal to the window that called it (so if I have two windows open, each window can have its own modal window). This means I can't use ShowDialog() as it blocks the entire application.
I implemented the solution proposed in this stackoverflow answer by using DispatcherFrames and Dispatcher.PushFrame(). This seemed to work, but after some testing I've found the following:
I start the application, open up a new window, open up a Modal window in the first window and then a Modal window in the second. Then I close the first Modal window, set the DispatcherFrame.Continue to false, but the PushFrame() does not return control to the code that called the method to show the modal window until the Modal window belonging to the second window has also been closed. I suspect this happens because when the first Modal window closes, it returns control to the second DispatcherFrame belonging to the other Modal window instead of the Application DispatcherFrame. However, if I close the second Modal window first, it works the way it should and returns control.
As an additional test, I tested the same situation in a fresh application with WPF MessageBoxes, and it turns out the same problem exists here as well.
MainWindow.xaml:
<Window x:Class="TestMessageBoxDispatcherFrame.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"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel>
<Button Click="OpenMessageBoxClick" Content="Open message box" />
<Button Click="OpenNewWindowClick" Content="Open new window" />
</StackPanel>
</Grid>
</Window>
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void OpenMessageBoxClick(object sender, RoutedEventArgs e)
{
var messageBoxResult = MessageBox.Show("Hello World!");
Console.WriteLine("MessageBox closed");
}
private void OpenNewWindowClick(object sender, RoutedEventArgs e)
{
var window = new MainWindow { ShowInTaskbar = true };
window.Show();
}
}
If I open up a second window, and open up a message box in each of these two windows, MessageBox.Show() will only return once the second opened MessageBox has been closed (so the first one blocks until the second one has been closed).
Is this a known issue? Working as intended? Are there any workarounds?
I have been able to create something close to what I want by using async/await, but this requires all methods that wants to call a MessageBox/Modal window to be async. What is the best way to show Modal windows the way I want?
I am working with wpf page control. Here I need to start application and open page in maximized state.
For window control it is quite easy by setting the state and position, but using page control it is bit tricky.
Below xaml of the first page which is startupuri.
<Page x:Class="MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
Title="MainWindow" ShowsNavigationUI="False" Background="#ffffff">
I am able to height and widht as maximum size using below code:
this.WindowHeight = System.Windows.SystemParameters.MaximizedPrimaryScreenHeight;
this.WindowWidth = System.Windows.SystemParameters.MaximizedPrimaryScreenWidth;
But screens opens at default location with screen overshooting the monitor visual area.
Need some help regarding this issue. thanks
You can set the page's parent Window to maximized state in the page's Loaded event handler, something like:
private void Page_Loaded(object sender, RoutedEventArgs e)
{
(this.Parent as Window).WindowState = WindowState.Maximized;
}