I am new to WPF. In winforms I used to create a presenter and new it up in the static main(). The presenter's constructor would be given a reference to to the main form before the form would be shown.
MainPresenter presenter = new MainPresenter(myform);
Application.Start(myform);
How can I do this in WPF? I noticed that App.xaml has a 'StartUri' property that specifies which form to load. Where is the main entry point to a WPF application and how do I change the default behavior here?
Thanks!
You could do this in the constructor or Loaded event of either the main form (specified in startUri) or in the App.xaml.cs file
This post demonstrates what I needed perfectly.
http://www.developingfor.net/wpf/accessing-command-line-arguments-in-wpf.html
Startup="Application_Startup"
This was added in the App.xaml Application declaration.
I then wired the event in the App.xaml.cs
private void Application_Startup(object sender, StartupEventArgs e)
{
}
This helped a lot too:
http://social.msdn.microsoft.com/forums/en-US/wpf/thread/e5757d5c-28f3-4233-8a5f-00116587d5c7
Related
So I'm still learning how to do C# applications and I have actually a problem with a window.
I've created a WPF project and I've separated some part of my main window in sub-parts (user-controls) so I can have a cleaner xaml code to work with.
I have a lot of different UserControl such as UserControlMenuStrip. All of them are inside the MainWindow.
Inside the MenuStrip was a MenuItem called Parameters :
<MenuItem Header="_Parameters" x:Name="MenuParameters"/>
I have created a new window called ParametersWindow. My goal was to open a child window centered with the main window when I click on the item.
But I don't really know how to proceed? Should I make a click= event and write down the code inside the linked UserControlMenuItem.xaml.cs linked file? Or in the MainWindow.xaml.cs file? Or maybe a new and clean file?
When I try to put it inside UserControlMenuItem.xaml.cs, I can't properly set the owner of the window I create this method but I can't set the owner:
private void OpenParametersWindow()
{
WindowParameters WinParam = new WindowParameters();
WinParam.Owner = MainWindow();
WinParam.WindowStartupLocation = WindowStartupLocation.CenterOwner;
WinParam.Show();
}
And, when I try via the MainWindow.xaml.cs I can't even get the variable...
So... How can I properly open the Window properly? And should I do it in the xaml.cs file or create a new one for a better understanding?
I've Created a class and added a static field as MainWindow to holding reference
class ReferenceClass
{
public static MainWindow mainWindow = null;//firstly null.we will set it in WindowLoaded event.
}
You can create a class like this for accessing reference of your MainWindow from wherever you want.Give your MainWindow reference to its static field.
MainWindow Loaded Event
private void Window_Loaded(object sender, RoutedEventArgs e)
{
ReferenceClass.mainWindow = this; //setting the reference to static field of ReferenceClass.
}
Menu Click (Event called on MenuStrip UserControl)
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
NewWindow nw = new NewWindow();
nw.Owner = ReferenceClass.mainWindow;//Calling the reference of MainWindow from our class.
nw.WindowStartupLocation = WindowStartupLocation.CenterOwner;
nw.Show();
}
Here we go
Project
This is just a way for solving this issue.We can find more solutions which are better than mine but i use this solution when i need.
A handle to the parent window for any usercontrol can be obtained that way:
Window wndParent = System.Windows.Window.GetWindow(this);
WinParam.Show(wndParent);
But when working with WPF, it is more convenient to use the MVVM pattern
As you writing UI in WPF it is preferred to implement it with MVVM pattern. It allows you to have a clear separation of concerns between code and presentation.
Regarding your question about how to set Owner I suggest reading this series of articles about dialogs in WPF implemented with MVVM in mind
https://www.c-sharpcorner.com/article/dialogs-in-wpf-mvvm/
I'm making a game library with C#.
I have a main Form which has a FlowLayoutPanel, which hosts the game library. There is an "add game" method in main Form which adds an item to FlowLayoutPanel, but this method is being called from a second form. But when I'm calling this method from this second form, nothing happens at all, but it works, if called from the main form.
Here's the code:
Here's the add game method in mainForm:
public void addIso()
{
PictureBox gameBox = new PictureBox();
gameBox.ImageLocation = "link here";
gameBox.Height = 200;
gameBox.Width = 150;
gameBox.SizeMode = PictureBoxSizeMode.StretchImage;
isoPanel.Controls.Add(gameBox);
}
This method adds a placeholder game to FlowLayoutPanel called isoPanel. Works when called from the same form.
And here's how the method is being called from second form:
private void addGameButton_Click(object sender, EventArgs e)
{
MainWindow mainForm = new MainWindow();
mainForm.addIso();
}
When I tried to add simple message box in the method, message box did show, but game wasn't added to FlowLayoutPanel.
Any tips or solutions?
I apologize for my poor english and messy programming terms, I started learning C# a little while ago.
You can achieve this by using delegate and Delegate.
What you are doing wrong here:
From addGameButton click event you are creating a new instance of the mainForm. Which is not the actual main form that you are currently seeing, its a different instance of the mainForm. your code adds the control to the layout just confirm this by calling mainForm.Show() this will opens a new form with the control.
What you can do:
In such cases, you want to modify the parent control, calling methods in parent class, you need to use delegates by the following way:
Changes needs to apply in the Parent class ie., MainWindow.
Define a delegate and an event of that delegate type.
public delegate void UpdateUiDelegate();
public event UpdateUiDelegate UpdateUiEvent;
Assign the required method to the Event(better use this in constructor):
public MainWindow ()
{
UpdateUiEvent+= new UpdateUiDelegate(addIso);
}
Next work is in the child form ie., Form2 (use a better name let it be ImageChildControl). Create a Delegate there:
public Delegate ControlCreator;
Come back to MainWindow, Locate the place where you are calling the Second form, after creating instance of the child form assign the created event to that Delegate of the instance, for that Use the following codes there:
ImageChildControl ImageChildControlInstance = new ImageChildControl();
ImageChildControlInstance.ControlCreator = UpdateUiEvent;
One more work to do in child form that is; Calling the delegate from the Button click event. ie.,
private void addGameButton_Click(object sender, EventArgs e)
{
ControlCreator.DynamicInvoke();
}
Now you can see your code works as you expected.
You seem to be recreating the form when you load the second form.
as this does lack a little context.
I suggest you have a main tread which will run the two forms
create a game manager class Ex: GameManager.cs
In the class create a variable for both forms and set them as protected.
in each form send a reference of the gamemanager to it.
which will allow each window to communicate with each other through the manager by provide secure inter communication.
Let me know if you would like some source with this.
I have a WPF window in a project with a XAML file and associated C# code behind file. If I set "StartupUri=MainWindow.xaml" in App.xaml to this window the window opens as expected when I start my application.
However, I want my application to to take command line parameters and then decided if it should open the GUI or not. So instead I've set "Startup=Application_Startup" in my App.xaml file which is defined as shown below.
private void Application_Startup(object sender, StartupEventArgs e)
{
if (e.Args.Length > 1)
{
//do automated tasks
}
else
{
//open ui
MainWindow window = new MainWindow();
this.MainWindow = window;
window.Show();
}
}
Yet when I run this the window displayed is totally blank.
Adding window.InitializeComponent() seems to do the trick:
MainWindow window = new MainWindow();
Application.Current.MainWindow = window;
window.InitializeComponent();
window.Show();
I usually like to have a little explanation on why something does or doesn't work. I have no clue in this case. I can see that the examples online don't include InitializeComponent, and yet I produce the same exact error as you do (event without checking for args).
I created a sample application, and removed the StartupUri and set the Startup to the method you provided. Everything seems to work as expected, the content of the window is displayed, so maybe, as Daniel mentioned, you're missing the call to InitializeComponent method in your MainWindow constructor.
I am learning WPF with M-V-VM. And I am using ICommand, RelayCommand.
I have several Views, Models, and ViewModels.
The MainWIndowView open upon on application start. The MainWindowView has a button that opens another WPF window called “FileListview” via MainWindowViewModel.
The FileListView has a button “View Lookup”, which supposed to open another WPF window called “LookupView” via FileListViewModel. But I could not make this button to work unless I specify FileListView in App.xaml.cs instead of MainWIndowView. I could not understand why “View Lookup” button work if I make application to start from “FileListView” . I also don’t understand whether I need model for MainWindowView, and FileListView since I don’t have anything going except one view’s button is opening another view.
On code behind file “App.xaml.cs” I have
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
WPFProject. MainWIndowView window = new MainWIndowView ();
MainWIndowViewModel VM = new MainWIndowViewModel ();
window.DataContext = VM;
window.Show();
}
}
I would appreciate if somebody can point me to good article or sample code using WPF with M-V-VM that reflect my issue.
Here is my approach to use dialogs/child windows with mvvm and wpf. please note the comment from sllev and post all relevant code.
After rethinking the issue, I was able to figure out the solution.
The cause of the issue: I was not associating View with it’s ViewModel class.
So I put the following code in code behind of FileListView.xaml.cs.
public partial class FileListView: Window
{
private FileListViewModel _ fileListViewModel = new FileListViewModel ();
public FileListViewModel ()
{
InitializeComponent();
base.DataContext = _fileListViewModel;
}
}
Thank you
I'm trying to run a window, close it, and then run a second window, in a similar way that seems to work with Windows Forms.
namespace WpfApplication1
{
public partial class App : Application
{
[STAThread]
public static void Main()
{
Application app = new Application();
//windowMain.Show();
app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
MainWindow windowMain = new MainWindow();
app.Run(windowMain);
Window1 window1 = new Window1();
window1.Show();
app.Run(window1);
}
}
}
I've set the Build Action in the App.xaml properties from ApplicationDefinition to Page, but the programme throws an exception when window1 is initialised. What am I doing wrong?
Edit: I've modified the xaml in App.xaml as suggested by first answer and edited main as suggested by the comment.
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml"
ShutdownMode="OnExplicitShutdown">
<Application.Resources>
</Application.Resources>
</Application>
but I'm still getting the exception.
OK this is what I've divined so far. The Solution Builder looks for a Main() function. Why its not a WinMain() function I'm still not a hundred per cent clear on. If there is no Main(), you get an error. You can have more than one Main() as long as the Project properties: "Application" page/tab: property: "StartUp Object" is set to point to one of the main()s. This is done from an automatically created drop down list.
When a “WPF Application” project is created, Visual Studio(VS) create an xaml file called “App.xaml”. This is a class declaration where “App” is derived from the “Application” Class. VS also automatically generates hidden files for an xaml file. It creates a “name.g.i.cs” file, when the xaml file is created. It creates a “name.g.cs” file the first time the project is built after the creation of the xaml file. In this case it creates “App.g.cs” and “App.g.i.cs”. These files are hidden by default. To view them, press the “Show all files” button at the top of the Solution Explorer, they can be found in “\ obj\86\Debug” folder. When you delete an xaml file the “name.g.i.cs” and the “name.g.cs” files remain and are not deleted.
The “App.xaml” file’s “build Action” property is set to “Application Definition” when created by VS. When this property is set to “Application Definition” a Main() function is automatically created in “name.g.i.cs”:
[System.STAThreadAttribute()]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
public static void Main()
{
WpfApplication8.App app = new WpfApplication8.App();
app.InitializeComponent();
app.Run();
}
When this property is set to “Page”, the Main() function is automatically removed by VS. You can create new “Application” derived classes in code or in xaml. I haven’t found a neat way to do it in xaml. There doesn’t seem to be a template for an xaml “Application” derived class. I created a “.cs” code file and then renamed it to an .xaml file. For some reason VS won’t allow you to have more than one xaml “Application” declaration file set to “Application Build”, it doesn’t even give you the option of choosing one in the "Project: Properties: Application": “Startup Object” property.
As you can see in the hidden Main(), an instance of “App” is instantiated and run. If using your own Main() function: an instance of, the base “Application” class, or an “Application” derived class (whether declared in code or in xaml), can be declared and run. The “Application” class should only be instantiated once and should only be run once. If the “Application” derived class is declared in xaml then a simple application can be run by using the StartUpUri property in the xaml file: StartupUri="Windowname.xaml". Alternatively the top level UI programme logic can be placed in a Startup event handler. If “Startup="Application_Startup" is placed in the “App.xaml” file then an event handler can be written:
private void Application_Startup(object sender, StartupEventArgs e)
{
MainWindow windowMain = new MainWindow();
windowMain.ShowDialog();
Window1 window1 = new Window1();
window1.ShowDialog();
Shutdown();
}
You have to use ShowDialog() here, because it blocks until the window is closed. If you used Show() instead, it would show one window, then immediately show the other one and shutdown the application. In this case there's no need to call the Run() method yourself, that's done automatically.
The “Application” class instance can be run in code whether its declared in code or in xaml. You can then perform initialisation code prior to calling Run(). This would be placed in the Application_ Startup() event handler using the other way. However, if the “Application.Run” call is ever made in the programme, then no windows should be opened (using show() or ShowDialog()) in Main() or anywhere outside of the Application Class or within events and functions called from those events, called during “Application.Run()”.
The Application class has a ShutdownMode property (Application.ShutdownMode). The default for this is: “OnMainWindowClose”. This property can also be set to “OnLastWindowClose” or “OnExplicitShutdown” in code or in the xaml. You will need to reset this if you don't want the programme to close down when the MainWindow is closed.
I think for my purposes it is better not to use the Application class at all and just call the windows using Show() and “ShowDialog()”. This way I can use WPF pages but I could also call Windows Forms, or DirectX screens, as long as they are not open at the same time, or have no UI at all, if the programme is running remotely. Is there any reason for not doing it this way?
I think your application is shuting down when you close the first window. You need to set Application.ShutdownMode to OnExplicitShutdown.
If all you want to do is to show one window, when that closes, show another and when that closes, shutdown the whole application, you should keep the Build action as ApplicationDefinition, set ShutdownMode to OnExplicitShutdown (probably in App.xaml, but you can it in code-behind too) and put the following code in an event handler of the Startup event of your application:
private void Application_Startup(object sender, StartupEventArgs e)
{
MainWindow windowMain = new MainWindow();
windowMain.ShowDialog();
Window1 window1 = new Window1();
window1.ShowDialog();
Shutdown();
}
You have to use ShowDialog() here, because it blocks until the window is closed. If you used Show() instead, it would show one window, then immediatelly show the other one and shutdown the application.
There's no need to run the Run() method yourself, that's done automatically.