I have a console project, but now I need to put an user interface on. So I'm using the 3 tier model (presentation, business, access data).
In my method Main() I call to presentation layer (like app in Window form or Wpf), so, in the presentation layer is the interaction with user through CONSOLE.
Now I add a window called "UserInterface.xaml" in the presentation layer to use instead of console. Because should be with INTERFACE not console.
I have observed that in MainWindow the called is with MainWindow.Show();
But I don't know how to call my "UserInterface.xaml", because has no .Show() method.
This is my method Main:
public static void Main()
{
MainWindow.Show(); // THIS IS WITH MainWindow.xaml
UserInterface.??? // THIS IS MY CASE WITH UserInterface.xaml
}
So can somebody tell me how I can call my window from the Main method??
You definitely got started with the wrong project template. To make a WPF window visible and interactive, you have to follow the rules for a UI thread. Which includes marking the main thread of your app as an STA thread and pumping a message loop. Like this:
class Program {
[STAThread]
public static void Main() {
var app = new Application();
app.Run(new MainWindow());
}
}
Beware that Application.Run() is a blocking call, it will not return until the user closes the main window. This is a rather inevitable consequence of the way Windows works.
Assuming UserInterface is really a window, this should work:
var window = new UserInterface();
window.Show();
Related
This code doesn't show the Window, it just closes automatically. Why is this happening?
class Program
{
[STAThread]
static void Main(string[] args)
{
var window = new MainWindow();
window.ShowDialog();
}
}
I know that you can fix it adding a new Application.Run(window) but I would like to know why it has this behavior and why you have to invoke the Run method over the window instance.
EDIT:
Extending the previous question, I've noticed that this code will work:
Create a new WPF Application.
Go to App.xaml and delete the StartupUri
Modify the App.xaml.cs overriding the method OnStartup
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var window = new MainWindow();
window.Show();
}
}
With this, the window remains open. What's going on under the hood?
Microsoft Windows programs are event-based. They act upon messages that the operating system posts to the main thread of the application. These messages are received from the message queue by the application by repeatedly calling the GetMessage (or PeekMessage) function in a section of code called the "event loop."
When Run is called, Application attaches a new Dispatcher instance to the UI thread. Next, the Dispatcher object's Run method is called, which starts a message loop to process windows messages. Finally, the Dispatcher object calls the Application object's OnStartup method to raise the Startup event.
Without a message loop, the application is unable to support the UI.
I've been studying Android lately and I tried to port one of its functions to C# compact framework.
What I did is create an Abstract class that I call Activity.
This class looks like this
internal abstract class Activity
{
protected Form myForm;
private static Activity myCurrentActivity = null;
private static Activity myNextActivity = null;
internal static void LoadNext(Activity nextActivity)
{
myNextActivity = nextActivity;
if (myNextActivity != null)
{
myNextActivity.Show();
if (myCurrentActivity != null)
{
myCurrentActivity.Close();
myCurrentActivity = null;
}
myCurrentActivity = myNextActivity;
myNextActivity = null;
}
}
internal void Show()
{
//PROBLEM IS HERE
Application.Run(myForm);
//myForm.Show();
//myForm.ShowDialog();
//
}
internal void Close()
{
myForm.Close();
}
internal void GenerateForm()
{
///Code that uses the Layout class to create a form, and then stores it in myForm
//then attaches click handlers on all the clickable controls in the form
//it is besides the point in this problem
}
protected abstract void Click(Control control);
//this receives all the click events from all the controls in the form
//it is besides the point in this problem
}
The problem I have is with running the part of the Show() command
Basically all my classes implement the above class, load an xml file and display it.
When I want to transition to a new class/form (for example going from ACMain to ACLogIn)
I use this code
Activity.LoadNext(new ACLogIn);
Which is supposed to load the next form, show it , and unload the current form
I have tried these solutions (in the Show() method) and here is the problem with each one
using myForm.ShowDialog()
This works, but blocks execution, which means that the old form does not close, and the more I move between the forms the more the process stack increases
using myForm.Show()
This works, closes the old form after the old one is shown, but immediately after that closes the program and terminates it
using Application.Run(myForm)
This works only on the first form loaded, when I move to the next form, it shows it then throws an exception saying "Value does not fall within the expected range"
Can someone help me fix this or find an alternative?
If you're really after creating your own framework for this navigation, you need to re-work you thinking. The Form instance passed into Application.Run must never close - when it does, Application.Run finishes execution and (typically) your static void Main entry point exits and the app terminates.
What I would propose is that you change your Activity to either being a UserControl:
public abstract class Activity : UserControl
{
....
}
or Composing one
public abstract class Activity
{
private UserControl m_control;
....
}
Then instead of closing and showing Forms, parent all of the Activities inside the main Form as a container.
As fair warning, this is going to get complex when you start wanting to show things in a Tab motif instead of a Stack, or having split views. Frameworks seem simple to create, but they're not so I'd at least consider using something already done unless you have compelling reasons to want to roll your own.
Application.Run is generally used with the overload that takes a Form parameter. This would be the "main" form that would be responsible for starting/showing other forms. This "main" form could be "hidden". But, I think that's a little awkward.
Alternatively, you don't need a main form, you can use Application.Run() to start a message pump to process Windows messages; but, then the thread is busy processing messages and cannot show dialogs (they must be shown in the thread that is running Application.Run). You can get around this by creating one or more form objects before calling Application.Run and these form objects could create a Timer object that would call Form.Show() or Form.ShowDialog() on the Timer.Tick event handler so that for form is shown after the call to Run. I think this is a little awkward as well.
Both of these solutions kind of circumvent the way you're expected to use Windows and WinForms; so, I think you need to think about re-designing this application to work with the way that Windows and .NET works.
I'm currently trying to use a WPF component that makes use of Application.Current from a WPF application, however due to several reasons I never call Application.Run (nor is that an option). The result is a NullReferenceException.
I'm basically trying to display multiple instances of the same WPF window from what would be a console application.
Any advice (and code samples in C#/F#) would be welcome!
Thanks in advance
Just to offer an alternative solution.
It is possible to keep an application running without any windows open. To me this feels less 'hackish'. :) http://msdn.microsoft.com/en-us/library/system.windows.application.shutdownmode.aspx
public class AppCode : Application
{
// Entry point method
[STAThread]
public static void Main()
{
AppCode app = new AppCode();
app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
app.Run();
...
app.Shutdown();
}
}
EDIT:
Ok this got a bit cumbersome. Application.Run will block, so it needs to run in its own thread.
When it does run in its own thread, any interaction between your main thread and your ui thread had best be done by Application.Current.Dispatcher.Invoke. Here is some working code, that assumes you have a class that inherits from Application. I'm using a modified App.xaml/App.xaml.cs that a WPF project template creates for you, to get nice handling of ResourceDictionaries for free.
public class Program
{
// Entry point method
[STAThread]
public static void Main()
{
var thread = new System.Threading.Thread(CreateApp);
thread.SetApartmentState(System.Threading.ApartmentState.STA);
thread.Start();
// This is kinda shoddy, but the thread needs some time
// before we can invoke anything on the dispatcher
System.Threading.Thread.Sleep(100);
// In order to get input from the user, display a
// dialog and return the result on the dispatcher
var result = (int)Application.Current.Dispatcher.Invoke(new Func<int>(() =>
{
var win = new MainWindow();
win.ShowDialog();
return 10;
}), null);
// Show something to the user without waiting for a result
Application.Current.Dispatcher.Invoke(new Action(() =>
{
var win = new MainWindow();
win.ShowDialog();
}), null);
System.Console.WriteLine("result" + result);
System.Console.ReadLine();
// This doesn't really seem necessary
Application.Current.Dispatcher.InvokeShutdown();
}
private static void CreateApp()
{
App app = new App();
app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
app.Run();
}
}
The following is the intended behavior of Application class:
The first open window is the MainWindow.
The only window in the list becomes the MainWindow (if others are to
be removed).
Application Class is designed to exit if no windows are present in
windows list.
Check this link.
So basically you cannot run an Application, without any window open. Keep a window open but hidden.
If I have misunderstood your problem, then perhaps the following similar cases might help:
Managing Application Resources when WPF is Hosted.
When running unit tests in Visual Studio 2008
I've got a mono app written in c# and executed on a Mac using "mono myapp.exe"
The app itself is a "Windows Application" when viewed from the project properties, but it doesn't always show a window. In program.cs, there is a static Main:
static void Main(string[] args) {
UserClient client = new UserClient();
client.Start(args);
}
public class UserClient {
public void Start(string[] args) {
// Talk to server, listen for instructions, etc.
....
// Launch the "Stay Alive" thread
// Just a thread that Sleeps/Loops watching for an exit command; mainly used to keep the process alive
}
}
Inside the UserClient's Start method, there is a piece of code that continuously monitors a server which gives it instructions to do things. One of the things it does is optionally displays a message using a windows form.
When the server instructs the process to display a message, it instantiates a form, displays it using frm.ShowDialog() and then after 30 seconds, a timer on the form runs Close() and the frm then gets disposed. However, when this happens, on my Mac I see an application title bar saying "mono" and a new icon on my dock bar for the mono app. After about 2 minutes the mono process in Activity Monitor shows "Not Responding." This eventually will prevent the user from logging out, shutting down, etc. (because Mac OS can't kill mono gracefully).
ON THE OTHER HAND... if the server never tells the process to display that form, everything runs fine and dandy: a dock icon never shows up (which is good!), mono title bar never shows up and the mono process continues to run happily, not preventing the system from shutting down or rebooting.
Anyone experienced this or have ideas on what's causing it? My guess is that it's a new GUI thread being created by the form which isn't ever being shutdown and is somehow causing a lockup, though I'm unsure of how to handle it.
Thanks for any suggestions.
Update:
Here's some code to easily reproduce and see this happening. I realize that this seems kind of "non-standard." Having said that, the below works perfectly in a Windows environment and provides the desired result of not showing an icon in the task area except when showing a message. Currently, using Application.Run and simply doing frm.ShowDialog() produce exactly the same result.
In the end what we need is to be able to display the form, then destroy the form and any associated icon from the dock. I suspect the GUI is starting a thread which isn't ever being disposed, which is why the dock icon remains. Is there a way to make sure the GUI thread is taken care of?
static class Program {
static void Main() {
StartupClass s = new StartupClass();
s.start();
}
}
public class StartupClass {
Thread stayAliveThread;
public void start() {
// Stay alive thread
stayAliveThread = new Thread(stayAliveLoop);
stayAliveThread.Start();
// This shows a form and would normally be used to display temporary and brief messages to the user. Close the message and you'll see the undesired functionality.
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
Application.Exit();
Application.ExitThread();
}
/// <summary>
/// Keep the app alive.
/// </summary>
private void stayAliveLoop() {
while (true) {
Thread.Sleep(10000);
// In the real project this method monitors the server and performs other tasks, only sometimes displaying a message.
}
}
}
I feel I'm missing several things. Most notably
[STAThread]
static void Main(string[] args) { //....
Also see this answer: Windows Forms and ShowDialog problem
I can't see anything like initializing message loop for windowed application. I.e. in windows forms case something like Application.Run(). If you do not have it, no wonder application freezes. In any case, posting more code could be helpful, as stated in comment.
In the end, I couldn't resolve this. I created a process that launched another app which displayed the message form. Not really a true answer, but the solution I had to go with.
Is it possible to call Application.Run, but to not pass a form parameter, or is there an alternative if there’s no form to call?
The Run method doesn’t seem to have any overloads that don’t accept a form.
For example, if I wanted to instantiate a class first, and then have that call the form, is there way to do the equivalent of:
Application.Run(myClass);
Just to clarify, I do still want the functionality that .Run() provides. That is, establish a loop to keep the application running, but instead of tracking a form, track a class or other object.
This is relating to the compact framework initially. I assume that's why the Run method doesn't have the overload I was looking for.
The Run method doesn’t seem to have any overloads that don’t accept a form.
Uh... http://msdn.microsoft.com/en-us/library/ms157900.aspx
Application.Run Method
Begins running a standard application message loop on the current thread, without a form.
public static void Run()
I'm not clear whether you want to do:
You want to load your form somewhere else other than the Main()
Or Run a console or service application with no UI.
For (1):
static void main()
{
//Your program starts running here<<<
//Do some stuff...
FormRunner a = new FormRunner();
a.RunForm();
} // << And ends here
class FormRunner {
public void RunForm() {
Application.Run(new Form());
}
//You could call which ever form you want from here?
} // << And ends here
What you need to know is your program starts from the first line of the main and ends at the last. However, when you call Application.Run(FORM) it loads up a windows message loop for that form. Its a special loop that keeps the program still in the main and waits for events (they're called Windows Messages in win32 API)
And so the program does not end until the user clicks the close button. When this happens, thats when your program actually will return from its Main.
(2) So now if you just want a pure console app with no forms:
static void main()
{
AcceptInputs()
DrawScreen()
//Do something else.
//Make sure your flow stays within the main
} // << Once you come here you're done.
void AcceptInputs()
{
while(true) {
//Keep accepting input
break; // Call break when you're done. You'll be back in the main
}
}
I hope that helped.
You can use the overload of Application.Run that accepts an application context as its only parameter. An ApplicationContext is basically just a class that you can inherit from and add any functionality you like. See the example in the link for more information.
using System;
using System.Windows.Forms;
static class Program
[STAThread]
static void Main() {
Application.Run(new myClass());
}
internal class myClass : ApplicationContext {
public myClass() {
Application.Run(new myWindow());
}
}
}
The problem here, though, is that something will have to call this instance of myClass and tell it to exit or else the program will just keep running even after all forms are closed. And calling ExitThread() in the constructor is ignored.