How can this be done
Login window appears first and if every thing is fine just close login window and open second Main window.
in win forms we modify program.cs but in wpf there is no program.cs.
Any solutions.?
Actully i did most of the work in the window that is created By default and now want to make it secondary(mean it should appear and then close when wanted giving control to new window)
<Application x:Class="DevnMark_V1._0.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="Application_Startup">
<Application.Resources>
</Application.Resources>
</Application>
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
var login = new MainWindow();
login.ShowDialog();
if (myAppSett.Default.validated == true)
{
var mainWindow = new DevNMarkMainWindow();
mainWindow.ShowDialog();
}
}
Login Window start XML
<Window x:Class="DevnMark_V1._0.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
xmlns:local="clr-namespace:Progress"
Title="MainWindow" Height="292" Width="563" WindowStyle="None" BorderBrush="#FF0A6277" AllowsTransparency="True" WindowStartupLocation="CenterScreen" Topmost="True">
Exception occurs when i close Login window and occurs at point InitializeComponent();of second window when it is viewed when it is going to be initilized
I solved this problem in this way:
I removed from App.xaml the StartupUri="MainWinodw.xaml", leaving only Startup="Application_Startup".
In Application_Startup, I IMMEDIATELY referenced both login and main windows:
loginwindow Login = new loginwindow();
mainwindow Main = new mainwindow();
I verified my Login, then closed the login window and opened the main window with a simple .Show():
Login.ShowDialog();
if (!Login.DialogResult.HasValue || !Login.DialogResult.Value)
{
Application.Current.Shutdown();
}
main.Show();
No changes in ShutdownMode.
There may be no program.cs, but there is an App.xaml.cs in the default WPF program template and you can do the same thing there.
What you want to do is remove StartupUri="LoginWindow.xaml" from App.xaml and then modify App.xaml.cs's constructor to invoke your login window and your main window, like this:
public App() : base() {
bool authenticated = false;
LoginWindow login;
while (!authenticated)
{
login = new LoginWindow();
login.ShowDialog();
authenticated = ValidUser(login.username, login.password);
}
MainWindow main = new MainWindow(login.username);
main.ShowDialog();
}
The above example assumes you've added username and password as public properties to LoginWindow, and that you've modified MainWindow's constructor to take a parameter.
The proposed OnExplicitShutdown method works and you can avoid explicitly shutting the app down in the second window simply by opening it with ShowDialog followed by this.Shutdown(), all in App.xaml thus not interfering with the rest of the application.
Related
So I've been doing research on this for quite a few weeks now, and haven't really come up with an answer on why this doesn't work properly... I've even researched JumpLists to see if this was what I was looking for, but also to no avail. This problem relates to when you attempt to select 'Close All Windows' by right clicking an app's icon on the task bar...
For example, here is an EXTREMELY small and simple WPF application I wrote to demonstrate the problem I am having. Here is the app's icon in the task bar with its choices on the context menu for it...
contextmenutoolbar
I am selecting the choice 'Close all windows', for reference (the bottom one, with the X to the left of it).
This is a WPF application and here is the code for App.xaml:
<Application x:Class="CloseAllWindows.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Application.Resources>
</Application.Resources>
</Application>
Here is App.xaml.cs, which launches the MainWindow. It also sets the application's MainWindow property to the MainWindow that is instantiated. It also sets ShutdownMode to be only when the main window is closed... I don't want the application to still run if the main window is closed and some secondary windows are left open.
using System.Windows;
namespace CloseAllWindows
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
ShutdownMode = ShutdownMode.OnMainWindowClose;
var mainWindow = new MainWindow();
Application.Current.MainWindow = mainWindow;
mainWindow.Show();
}
}
}
Here is the code for MainWindow.xaml:
<Window x:Class="CloseAllWindows.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:CloseAllWindows"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<Button Content="NewWindow" Click="ButtonBase_OnClick"></Button>
</StackPanel>
</Window>
And here is the code behind for it... which launches a secondary window when I click a button. It is setting the parent window (Owner property) to the main window, like all the examples I've seen say it should be set, and then call Show() on it.
using System;
using System.ComponentModel;
using System.Windows;
namespace CloseAllWindows
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
var childWindow = new ChildWindow {Owner = this};
childWindow.Show();
}
}
}
Here is the code for the child window, ChildWindow.xaml:
<Window x:Class="CloseAllWindows.ChildWindow"
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:CloseAllWindows"
mc:Ignorable="d"
Title="ChildWindow" Height="300" Width="300">
<Grid>
</Grid>
</Window>
And it's corresponding code behind, ChildWindow.xaml.cs:
using System;
using System.Windows;
namespace CloseAllWindows
{
/// <summary>
/// Interaction logic for ChildWindow.xaml
/// </summary>
public partial class ChildWindow : Window
{
public ChildWindow()
{
InitializeComponent();
}
}
}
As you can see, these classes do not do very much... it was the simplest example of code I could write that shows the problem I am having. So the issue is, if I select Close all windows from the task bar context menu, it never closes all the windows. Instead, it will close the one child window, and still leave the main window open. Interestingly, I hear the windows dialogue chime when I do this, almost like its getting interrupted by something, but I have no idea what.
It also appears to act very randomly... if I spawn 20 windows, it will sometimes close 6 of the windows, then all of them... sometimes it will close a few windows one by one, then close the rest... sometimes it will close all child windows and leave only the main window open. Needless to say, I am pretty baffled as to the behaviour since it doesn't seem to follow any noticeable pattern... any help greatly appreciated! And hopefully the example is good enough to explain what I am trying to get at....
Well you could add an event that will close every window the event is implanted in. try this example:
step 1: add a class to your project call it whatever you want, I called it CloseWindowListener, add this code to your class:
public static class CloseWindowListener
{
public static event EventHandler<EventArgs> ClosingWindows;
public static void CloseWindows()
{
var CWindows = ClosingWindows;
if (CWindows != null)
{
CWindows(null, EventArgs.Empty);
}
}
}
step 2: Add the event handler to the window you desire to close when it is called.
public partial class TestWindow1 : Window
{
public TestWindow1 ()
{
InitializeComponent();
CloseWindowListener.ClosingWindows += CloseWindowListener_ClosingWindows;
}
private void CloseWindowListener_ClosingWindows(object sender, EventArgs e)
{
this.Close();
}
}
step 3: simply call the event from your main window or where ever you want.
private void button_Click_1(object sender, RoutedEventArgs e)
{
CloseWindowListener.CloseWindows();
}
How do I get access to MessageBox using the low level WPF Automation API?
I have searched all over but there seems to be very little documentation for this. I would rather not use White as I need more control than it gives.
Thanks
Lets suppose you have that simple WPF application:
Xaml:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<Button Name="Button1" Content="Click Me" Click="Button1_Click" />
</Grid>
</Window>
Code:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void Button1_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(this, "hello");
}
}
You can automate this application with a console app sample like this (run this once you have started the first project):
class Program
{
static void Main(string[] args)
{
// get the WPF app's process (must be named "WpfApplication1")
Process process = Process.GetProcessesByName("WpfApplication1")[0];
// get main window
AutomationElement mainWindow = AutomationElement.FromHandle(process.MainWindowHandle);
// get first button (WPF's "Button1")
AutomationElement button = mainWindow.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button));
// click it
InvokePattern invoke = (InvokePattern)button.GetCurrentPattern(InvokePattern.Pattern);
invoke.Invoke();
// get the first dialog (in this case the message box that has been opened by the previous button invoke)
AutomationElement dlg = mainWindow.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.LocalizedControlTypeProperty, "Dialog"));
AutomationElement dlgText = dlg.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Text));
Console.WriteLine("Message Box text:" + dlgText.Current.Name);
// get the dialog's first button (in this case, 'OK')
AutomationElement dlgButton = dlg.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button));
// click it
invoke = (InvokePattern)dlgButton.GetCurrentPattern(InvokePattern.Pattern);
invoke.Invoke();
}
I have written a WPF program that when user clicked a button, a new window will be popped up.
I have tried to show the new window by using Show() or ShowDialog() function.
In Windows 7, when user closed the child window, the main window will remain and the program will not exit. This behavior is what I want to have.
However, when the program is run in Windows XP, when user closed the child window, the main window will be closed together and the whole program will be exited.
I have tried to set different value in different properties in Window class, finally, I found that the program will not exit only when I set the property "ShowInTaskbar" to "False" in child window.
However, if ShowInTaskbar is set to false, user cannot find the entry in task bar which is not the behavior that I want.
What I want to have is really simple. I just want the program running in Windows XP to have the same behavior as the program running in Windows 7 when user closed the child window (i.e. main window will not exit when user closed the child window). Also, I want to have an entry in task bar for a newly created child window(i.e. ShowInTaskbar = true).
Does anyone have any idea about this problem?
MainWindow
<Window x:Class="ChildWindowTest.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">
<Grid>
<Button Click="OpenChild">Open Child Window</Button>
</Grid>
</Window>
Code For MainWindow:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void OpenChild(object sender, RoutedEventArgs e)
{
ChildWindow child = new ChildWindow();
child.Owner = this;
//child.ShowInTaskbar = false; <--- if comment, the program will exit, when child window closed
child.Show();
}
}
Child Window:
<Window x:Class="ChildWindowTest.ChildWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ChildWindow" Height="300" Width="300">
<Grid>
</Grid>
Code for Child Window:
public partial class ChildWindow : Window
{
public ChildWindow()
{
InitializeComponent();
}
}
Not an elegant solution at all, but you always can subscribe to Closing event in Application class and cancel application closing in an event handler.
Did u make sure you have childWindow.Owner set as our MainWindow correctly before calling childWindow.ShowDialog()?
I've been trying for hours to get to the point where I can start a WPF application and have full control. I want to be able to create a ViewModel, create a View (Window), set the data context of the View to be the ViewModel, then show the View.
I've tried lots of methods, the most promising being to change the App.xaml to be a page and then adding my own Main method. Unfortunately this doesn't work properly because VS2010 then does not show the styles from the App.xaml in the designer, though they do work when running the app.
Is there a way to do what I want? If not, how do people normally start MVVM apps in WPF, creating a ViewModel outside of the View itself?
I would use the Startup event. You can add this to the App.xaml and remove the StartupUri line. When you add it, Visual Studio can create the event for you within the App.xaml.cs file. You can initialise your ViewModel and View within.
Here is one simple way...
<Application
x:Class="Demo.Ux.WpfApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Application>
Here is the basic App.xaml.cs
public partial class App
{
protected override void OnStartup(StartupEventArgs e)
{
try
{
var mainView = new MainView();
mainView.Show();
mainView.DataContext = new MainViewModel();
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
}
Application.MainWindow can be used as well. The first displayed Window will be assigned to MainWindow auto-magically. Of course, you can skip creating your mainView and write directly to MainWindow which would thin out the syntax as well.
MainWindow = new MainView();
MainWindow.Show();
MainWindow.DataContext = new MainViewModel();
One final note, I'm doing the Show before the data bind. You need to do this to avoid a situation where the MainViewModel throw an exception during creation. If the MainView hasn't been shown, the app will close without letting you see the error.
in our application, we have choosen the way which you already proposed: writing a new Main method. You also have to make some changes in the project application settings then (no startup object). The app xaml has to look something like this:
<Application x:Class="EVOCURA.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="Application_Startup"
Exit="Application_Exit">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!--Custom Controls-->
<ResourceDictionary Source="<your resources here>"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
The code behind will look something like this:
public sealed partial class App : Application
{
static App()
{ }
public App()
{ }
private void Application_Startup(object sender, StartupEventArgs e)
{
// create the main window and assign your datacontext
MainAppWindow main = new MainAppWindow();
main.DataContext = <your datacontext here>
main.Show();
}
[STAThreadAttribute]
public static int Main(string[] args)
{
App app = new App();
app.InitializeComponent();
app.Run();
return 0;
}
}
Have a look at the Startup Event and notice, that no default StartupUri is specified im App.xaml
You could also pass the DataContext in a new constructor of your MainWindow, or create the DataContext directly in xaml.
The simplest way to assign an instance of the ViewModel to the DataContext of the view is in the code behind of the Window.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new myViewModel();
}
}
For the first part of your question, you can have the control of your application in the StartUp event
<Application x:Class="myApplication.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml" Startup="Application_Startup">
<Application.Resources>
</Application.Resources>
</Application>
Code Behind :
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
// Place your code here
}
}
I have a ComboBox with ItemsSource="{DynamicResource testResource}". The testResource is the Application resource that I set in C# code.
What I have noticed is that if I load Window befor Application created, the resource is not loaded by ComboBox:
Window window = (Window)LoadXaml("Window1.xaml");
Application app = new Application();
This code works
Application app = new Application();
Window window = (Window)LoadXaml("Window1.xaml");
Also, even if I created the window befor the application, I can load resource latter in button click handler.
Can some one explain, what happens? Why the order matters?
Window1.xaml:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<StackPanel>
<ComboBox ItemsSource="{DynamicResource testResource}" SelectedIndex="0"></ComboBox>
<Button x:Name='testButton'>Test</Button>
</StackPanel>
</Window>
C#
class Program
{
[STAThread]
public static void Main()
{
Window window = (Window)LoadXaml("Window1.xaml");
Application app = new Application();
SetupResource();
(window.FindName("testButton") as Button).Click += new RoutedEventHandler(testButton_Click);
window.Show();
app.Run(window);
}
static void testButton_Click(object sender, RoutedEventArgs e)
{
SetupResource();
}
static void SetupResource()
{
List<string> list = new List<string>();
list.Add("Hola");
list.Add("Mundo");
Application.Current.Resources["testResource"] = list;
}
static object LoadXaml(string fileName)
{
return XamlReader.Load(File.Open(fileName, FileMode.Open));
}
}
Not sure, but I would guess because the Application's Resources are only loaded when the Application object is created. So if you want to access testResource, you need to do it after the call to new Application().