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
Related
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:
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 have three XAML files, they are mainwindow.xaml,login.xaml,homepage.xaml. Since the files can be navigated through frames, i added a frame to main window which fits the whole screen.
XAML of MainWindow:
<Window x:Class="Myproject.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" WindowState="Maximized" Initialized="Window_Initialized">
<Grid>
<Frame Name="pageFrame"></Frame>
</Grid>
</Window>
CS file of MainWindow:
private void Window_Initialized(object sender, EventArgs e)
{
pageFrame.Height = SystemParameters.WorkArea.Height-10;
pageFrame.Width = SystemParameters.WorkArea.Width;
pageFrame.Navigate(new login());
}
It navigates perfectly to login page and perform login actions there.
The problem is it does not navigate to the homepage.xaml from the login.xaml.cs
Code used for navigating to homepage.xaml from login.xaml.cs
MainWindow mw = new MainWindow();
mw.pageFrame.Navigate(new homepage());
This code goes in a if statement section and i checked by using breakpoints if these statements are executed. And it does execute those and the objects are populated but the naviagtion does not occur.
What am i doing wrong? Is this not the correct approach?
The problem is, well, mw is a new window and it is not even shown at all. And you are staying in your old instance of MainWindow, nothing happens to your old MainWindow.
You need to navigate from within your old MainWindow, not a new one.
((MainWindow)(Application.Current.MainWindow)).pageFrame.Navigate(new homepage());
You have a reference to your main window, Application.Current.MainWindow, but you need to cast it into your own type of MainWindow first.
Certain elements of my application have custom resizing events, which all work. However, they are messed up by one case:
When hovering over the border of the window, so that the cursor becomes the resize handle, and you click (but do not drag), the elements resize incorrectly, and my handlers are not fired.
I've looked for such an event but cannot find anything that matches. I'd like to simply make a handler for this event to avoid glitchy resizing of my elements.
I'm using C#/WPF, with .NET 4
xaml for the window:
<Window x:Class="XHealth.MainWindow"
Name="mainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DataGridTemplateSample"
xmlns:XH="clr-namespace:XHealth"
xmlns:toolkit="http://schemas.microsoft.com/wpf/2008/toolkit"
SizeChanged="update_size"
Title="XHealth" Loaded="Window_Loaded" WindowState="Normal" WindowStartupLocation="CenterScreen" mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" SizeToContent="WidthAndHeight" WindowStyle="ThreeDBorderWindow" MinWidth="650" MinHeight="648" Width="Auto" VerticalAlignment="Top" DataContext="{Binding}" PreviewKeyDown="Window_KeyDown">
Event handler:
public void update_size(object sender, RoutedEventArgs e )
{
if (resultsTab.IsSelected){
Grid.SetRowSpan(dataGrid1, 2);
Grid.SetRowSpan(dataGrid2, 2);
}
}
This handler performs as intended, but does not trigger when the resize handle is not dragged, which leads me to believe clicking the resize handle is a different event.
Also, this only happens once - once my resize handler takes effect, clicked the resize handle has no effect.
Converting my comment into an answer:
That could be resolved by not putting any * in the Grid.
Also, if the Window is set to SizeToContent, you should only SizeToContent=Width to prevent the window from scaling endlessly.
Remove all the event handlers stuff, that's hack.
I want to perform a particular action when user cancels my dialog by clicking the close button (red X button)
and not when the form is closing because of some other operation. How i can determine whether the
private void Window_Closing(object sender, CancelEventArgs e)
event is raised by the button ?
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="60" Width="284" WindowStartupLocation="CenterScreen"
BorderBrush="#FFCCCCCC"
BorderThickness="2"
Background="#FFE0E0E0"
WindowStyle="SingleBorderWindow"
ShowInTaskbar="False" ResizeMode="NoResize" Closing="Window_Closing">
public MainWindow()
{
InitializeComponent();
this.Closing+=new System.ComponentModel.CancelEventHandler(MainWindow_Closing);
}
private void MainWindow_Closing(object sender, EventArgs e)
{
MessageBox.Show("salman");
}
My question is what are the other ways of closing this window? My understanding is the sender is always going to be the Window.
I would do the following - for all buttons or user based close - set a public property on the Window (something like bool ClosedByUser) and set it to "true" and then call Close().
For other cases (such as closing by clicking "X"), the property is by default set to false. In the closing event handler, use the property to make the decision.
Please note: There are other questions and answers similar to this on StackOverflow.