In the first window of my App there is a button to open a second window and in the second window there is also a button to open a third window. All Button-Commands are implemented in my ViewModel.
The current window must be closed before a new window is opened.
To go from the first to the second window, I used the following code:
void OpenSecondWindowExecute()
{
System.Windows.Application.Current.MainWindow.Hide();
SecondWindow sw = new SecondWindow();
sw.WindowStartupLocation = WindowStartupLocation.CenterScreen;
sw.Show();
}
bool CanOpenSecondWindowExecute()
{
return true;
}
public ICommand OpenSecondWindow { get { return new RelayCommand(OpenSecondWindowExecute, CanOpenSecondWindowExecute); } }
and it works fine because first window represents the MainWindow.
Problem:
How can I realize this with the other windows?
try this:
void OpenSecondWindowExecute()
{
this.Close();
SecondWindow sw = new SecondWindow();
sw.WindowStartupLocation = WindowStartupLocation.CenterScreen;
sw.Show();
}
Related
I'm running WPF application which can show windows and dialogs on top of the main screen of the application (.NET Framefork 4.7.2)
I use IWindowManager interface to call ShowWindow and ShowDialog.
When I want to show some window
Execute.OnUIThread(ShowPostProcessingLoadingMsg);
private void ShowPostProcessingLoadingMsg()
{
Logger.Info("PostProcessingToolViewModel: ShowPostProcessingLoadingMsg()");
if (_processingProgressMsg != null)
{
Logger.Warn("PostProcessingToolViewModel: ShowPostProcessingLoadingMsg() Loading msg was actibe already, closing it and creating a new one.");
_processingProgressMsg.TryClose();
}
_processingProgressMsg = new LoadingMessageViewModel()
{
ShowProgressRing = Visibility.Hidden,
ShowProgressBar = Visibility.Visible,
LoadingVisualState = LoadingVisualState.Mini
};
_progress = _processingProgressMsg.Progress;
_progress?.Report(0);
_updateProgressText = _processingProgressMsg.SetMessage;
_WindowManager?.ShowWindow(_processingProgressMsg);
}
And during it I show a dialog on other thread -
private void ShowPopupInDesktop(BatteryViewModel batteryPopupViewModel)
{
_logger.Info("BatteryViewModel::ShowPopupInDesktop: Going to show battery dialog");
_isPopupOpen = true;
SetPopupPosition(batteryPopupViewModel);
_windowManager.ShowDialog(batteryPopupViewModel, BatteryPopupViewContextName);
}
Then the window which I showed disappears.
I don't know how to keep the window opened and why does the dialog make it disappear.
I have an application that has a lot of modal popup windows. Some are custom windows displayed with .ShowDialog(), other are generic message boxes using a 3rd party tool (DXMessageBox.Show(...)), and others are system dialogs such as an OpenFileDialog. If the user leaves the application running long enough, it should time out and show a "Session Locked" screen and prevent users from seeing or interacting with the application until they login again. This is problematic because of the modal dialogs.
My current solution is to host the Relogin screen in the current modal window if there is one, and hide all other windows. The problem is that if I set Visibility = Hidden on any window I have called using .ShowDialog(), it treats that dialog as having received a result and processes the code that handles the dialog result. They are also no longer modal after they are re-shown.
So my current attempt is to try to hide the window using something other than Visibility, and prevent it from being activated. The closest I've come is by setting Minimized=true and ShowInTaskbar=false, but this results in an undesirable minimized titlebar above my taskbar.
Is there a way to prevent this from happening, or alternatively is there another way to hide a window and prevent it's activation without causing .ShowDialog to return?
Here's some code to re-create a sample application to test this with. Just add a button to launch the ShowLock_Click event handler.
private readonly Dictionary<System.Windows.Window, WindowStyle> _hiddenWindows = new Dictionary<System.Windows.Window, WindowStyle>();
// Create a button to launch this for testing
private void ShowLock_Click(object sender, RoutedEventArgs e)
{
// Will show another window with .ShowDialog, then 2s timeout will trigger lock window
using (new System.Threading.Timer(OnLockTimerElapsed, null, 2000, System.Threading.Timeout.Infinite))
{
ShowTestDialog();
}
}
private void OnLockTimerElapsed(object state)
{
_hiddenWindows.Clear();
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() =>
{
var mainWindow = Application.Current.MainWindow;
Window host = null;
foreach (Window win in Application.Current.Windows)
{
if (IsModalDialog(win))
host = win;
_hiddenWindows.Add(win, win.WindowStyle);
// Been testing various ways to hide window without using Visibility
win.ShowInTaskbar = false;
win.WindowStyle = WindowStyle.None;
win.WindowState = WindowState.Minimized;
win.Opacity -= 1;
win.IsHitTestVisible = false;
}
ShowLockScreen(host);
}));
}
private void ShowLockScreen(Window owner = null)
{
var lockScreen = new Window
{
Title = "Relogin Window",
Content = "This is a test Relogin Window. Close Window via X to continue",
WindowStartupLocation = WindowStartupLocation.CenterScreen
};
if (owner != null)
lockScreen.Owner = owner;
lockScreen.ShowDialog();
// Once that window closes, restore other windows
RestoreSession();
}
private void RestoreSession()
{
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() =>
{
foreach (var win in _hiddenWindows.Keys)
{
win.ShowInTaskbar = true;
win.WindowStyle = _hiddenWindows[win];
win.WindowState = WindowState.Normal;
win.IsHitTestVisible = true;
win.Opacity += 1;
}
}));
}
private void ShowTestDialog()
{
var test = new Window
{
Title = "Test Modal Dialog",
Content = "This is a test Modal Dialog. Close window via X to continue.",
Height = 100,
Width = 350,
WindowStartupLocation = WindowStartupLocation.CenterOwner,
Owner = this
};
var result = test.ShowDialog();
// This code gets run if I set Visibility=Hidden. I do not want that.
MessageBox.Show($"Test Dialog result returned. Result : {result}. This should ONLY happen when you click X on the dialog window");
}
private static bool IsModalDialog(Window window)
{
return (bool)typeof(System.Windows.Window)
.GetField("_showingAsDialog", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)
.GetValue(window);
}
I have a WPF C# using FirstFloor MUI Framework app, that on start, checks for settings and will show the specific startup uri as per below;
if(somethings_true) {
Application curApp = Application.Current;
//ModernWindow
curApp.StartupUri = new Uri("MainWindow.xaml", UriKind.RelativeOrAbsolute);
}else{
Application curApp = Application.Current;
//ModernWindow
curApp.StartupUri = new Uri("OtherWindow.xaml", UriKind.RelativeOrAbsolute);
}
which works fine, however when the "OtherWindow.xaml" is active first it has a onclick event that does other checks, and on finishing opens the MainWindow.xaml. But in the Button_Click() which does the opening of MainWindow.xaml, I cant get the OtherWindow.xaml to close and ive tried inside OtherWindow.xaml..
this.Close();
&
var OtherWin = new OtherWindow();
OtherWin.Close();
&
var w = Application.Current.Windows[0];
w.Hide();
//Only hides the OtherWindows.xaml (Still runs hidden in background even after MainWindow.xaml is closed)
I use the below code to check if OtherWindow.xaml is still open inside MainWindow.xaml in which it states that it does;
foreach (var wndOtherWindow in Application.Current.Windows)
{
if (wndOtherWindow is OtherWindow)
{
//Its Open Still...
//How to close() "OtherWindow.xaml" from here?
}
}
Is there another way to close() the OtherWindow.xaml?
You should cast to Window or specific type(in your case OtherWindow), that way you can call Close() method. Try this:
foreach (var wndOtherWindow in Application.Current.Windows)
{
if (wndOtherWindow is OtherWindow)
{
(wndOtherWindow as Window).Close();
}
}
Hope helps.
i have this WPF application in which i am trying to make popup window. well window is created and working fine, but what i want to do. that if i press OK/Update button in that popup, The selected values should be passed the the parent window and that popup should be closed.
i have seen this problem solution here..
C# - Return variable from child window to parent window in WPF
But i do not understand how this delegates works..
I have done it like this..
When click on button this method will opens the popup window.
private void btnAddBeneficiaryPopup_Click(object sender, RoutedEventArgs e)
{
try
{
AddBeneficiaryPopup addBen = new AddBeneficiaryPopup(refCustId);
addBen.selectedBeneID += value => selectedBeneficiaryID = value;
addBen.Show();
}
catch (Exception ex)
{ this.MyErrorMessage(ex); }
}
In Popup window in the constructor i have code like this.
public AddBeneficiaryPopup(int id)
{
InitializeComponent();
refCustId = id;
this.LoadReferenceBeneficiary();
}
Now this below Method i am working on and want to change it mostly..
private void cmbRefBene_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
string beneId = null;
if (cmbRefBene.SelectedIndex >= 0)
{
try
{
beneId = ((DataRowView)cmbRefBene.SelectedItem).Row.ItemArray[0].ToString();
selectedBeneID = beneId;
bene.OpenConnection(str);
SqlDataReader reader = bene.LookUpSingleBene(int.Parse(beneId));
if (reader.Read())
{
tbName.Text = reader["Name"].ToString();
tbContactNo.Text = reader["ContactNo"].ToString();
btnUpdate.IsEnabled = true;
}
reader.Close();
bene.CloseConnnection();
}
catch (Exception ex)
{
MyErrorMessage(ex);
}
finally
{
bene.CloseConnnection();
}
}
}
As you can see in above code selectedBeneID = beneId; this beneId gives error. as i am trying to assign it selectedBeneID, as i think its a delegate to there must be another way to assigning values to it and passing it to the Parent Window..
But really am not sure how to work with this delegate and what to write to assign value to it.
i am getting error
"cannot implicitly convert type string to "System.Action<string>"
Solution A (getting your one working)
To get your solution running, change the following line in your cmbRefBene_SelectionChanged function:
selectedBeneID = beneId;
to
selectedBeneID(beneId);
Now you should not get the error message and the value should be set correctly.
Solution B
The following solution isn'n the most elegant but it always works:
Give your Popup Window a public Property (selectedBeneID).
public partial class AddBeneficiaryPopup : Window {
public string selectedBeneID;
.....
}
}
Set this property in your cmbRefBene_SelectionChanged function.
MainWindow:
change addBen.Show(); in your Main Window
to
addBen.ShowDialog();
idreturned = addBen.selectedBeneID;
Now The program will wait until you close the Popup.
After that you can access the property of your popup Window and read it out.
Hope this makes sense.
I have something like this:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
if (!Directory.Exists(dataFolder))
{
Directory.CreateDirectory(dataFolder);
}
try
{
using (DataContext context = new DataContext())
{
context.Database.CreateIfNotExists();
}
}
catch (IOException ex)
{
}
KeyProgram.Show();
if (Manager.KeyExists == true)
{
MainWindowViewModel viewModel = new MainWindowViewModel();
this.MainWindow = new MainWindow();
this.MainWindow.DataContext = viewModel;
this.ShutdownMode = System.Windows.ShutdownMode.OnMainWindowClose;
Helper.WindowDialogService.SetOwner(this.MainWindow);
viewModel.Init();
this.MainWindow.Show();
}
else {
Console.WriteLine("Please try again");
}
}
After showing my licensekey window, I want to break so that the system wants for the user input (Have the user type in license key) then proceed to run the if-else statement (at if (LicenseKeyManager.licenseKeyExists == true)).
However currently, onStartup, the application just runs all of the code first then if I type in the key and validate it, it does not run that if statement because it has already ran.
How do I break for the user input from the view before continuing to that if-statement?
Right now after LicenseKeyProgram.Show(), if I set a breakpoint at the if-statement, the application won't let the user input anything because it's stuck on loading (Can't perform any action on the window).
Do I need an event handler here or...?
Use ShowDialog instead than Show.
Relevant MSDN link:
http://msdn.microsoft.com/en-us/library/system.windows.window.showdialog%28v=vs.110%29.aspx
Oh wait, one more question, I can get the user input but the appplication does not ever run/hit the if-else statement? Why?
You have to setup the mainwindow before calling the showdialog on your other window or else it'll trigger the shutdown of the application (since the application will shutdown when all windows are closed).
Example:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow window = new MainWindow();
Window1 test = new Window1();
test.ShowDialog();
if (test.InvalidLicense)
{
Shutdown();
return;
}
window.Show();
}
Ressources:
WPF showing dialog before main window
http://www.ageektrapped.com/blog/the-wpf-application-class-overview-and-gotcha/