How to open a file by double clicking in C# WPF? - c#

I need the file to open when the user double-clicks it in explorer, just like if you double-clicked a .txt file to open in Notepad. My program simply opens to the starting window, rather than the edit window. I want the start window to get it and pass it to the edit window. I can pass it to the edit window, but I can't figure out how to get the file path to the start window.
I have tried getting the environment arguments, which returns something weird, and not the file that the user double clicked.
I am not asking how to associate files with my program, which I can find out. I am only asking about how to open the file the user double-clicks in explorer.
Here's my code:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Container.Children.Clear();
Container.Children.Add(new NewFilePage());
if (Environment.GetCommandLineArgs().ToString() != null)
{
new EditorWindow(Environment.GetCommandLineArgs().ToString()).Show();
}
}

File association;
Modify App.xaml and App.xaml.cs in the WPF Application:
In App.xaml, remove the StartUp tag. Then subscribe to the Startup event, replacing the StartupUri property.
<Application x:Class="WpfTutorialSamples.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>
The event is then implemented in App.xaml.cs:
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
MainWindow wnd = new MainWindow();
if(e.Args.Length == 1)
wnd.FullFilePath = e.Args[0];
wnd.Show();
}
}
After these, the command-line parameters would be stored in e.Args. You can send these data to a property of your MainWindow class.

I'm not sure I follow what the problem is here.
I created an app with mainwindow and window1. I then overload the constructor of each window so they take a string parameter.
Application startup grabs the parameter and passes it in:
private void Application_Startup(object sender, StartupEventArgs e)
{
string passed = string.Empty;
if (e.Args.Length > 0)
{
passed = e.Args[0].ToString();
}
var mw = new MainWindow(passed);
mw.Show();
}
Since this is just a quick n dirty proof of concept I then pass in the parameter to window1 and show it.
That sets the text of a textblock successfully:
public partial class Window1 : Window
{
public Window1(string passed)
{
InitializeComponent();
tb.Text=passed;
}
public Window1()
{
InitializeComponent();
}
}
It has the full file path.
You could then do whatever you need to do with that file.

Related

What is the previous window called in WPF

I know the current window can be used with "this" but is there anything I can use to call the previous window?
For example I have this code going off when I press a button
Buyer_Login BuyerWindow = new Buyer_Login();
Visibility= Visibility.Hidden;
BuyerWindow.Show();
I need to be able to go back to the first window and I need to close the BuyerWindow and I was going to do it with this.Close();
What can I do to make the first window's visibility visible again?
You could handle the Window.Closed event:
MainWindow.xaml.cs
private void OnClick(object sender, EventArgs e)
{
var loginWindow = new BuyerLogin();
loginWindow.Closed += OnBuyerLoginWindowClosed;
this.Visibility = Visibility.Hidden;
loginWindow.Show();
}
private void OnBuyerLoginWindowClosed(object sender, EventArgs e)
=> this.Visibility = Visibility.Visible;
You should consider to show the login window from the App.xaml.cs before you show your main window (recommended):
App.xaml.cs
private async void App_OnStartup(object sender, StartupEventArgs e)
{
var loginWindow = new BuyerLogin();
bool? dialogResult = loginWindow.ShowDialog();
if (dialogResult.GetValueOrDefault())
{
var mainWindow = new MainWindow();
mainWindow.Show();
}
}
App.xaml
<Application Startup="App_OnStartup">
<Application.Resources>
</Application.Resources>
</Application>
There is a collection of open windows.
App.Current.Windows;
It depends on exactly what you're doing opening windows.
If you start up then mainwindow will be [0] in that collection.
Say you then open an instance of window1.
That in turn opens an instance of window2.
There is a bit of a complication if you f5 in visual studio because it opens adorner windows.
Setting that aside for a moment.
When I write code to do what I describe above.
In Window2 I handle content rendered:
public partial class Window2 : Window
{
public Window2()
{
InitializeComponent();
}
private void Window_ContentRendered(object sender, EventArgs e)
{
var wins = App.Current.Windows;
wins[1].Close();
}
}
That instance of Window1 is closed.
Your new window is very likely the last window in that zero based collection and the previous one the window before that.
You could perhaps search the collection and find index for "this" and subtract one if you're doing more complicated things.
The chances are though, you want to close the window indexed by the count of that collection minus 2. Because it's zero based.
With my exploratory code, window1 closes with this:
private void Window_ContentRendered(object sender, EventArgs e)
{
var wins = App.Current.Windows;
wins[wins.Count - 2].Close();
}
Personally, I prefer single window apps and switch out the content in part of mainwindow. Leaving navigation buttons etc static in mainwindow.
If you're effectively opening one other window and closing the previous to do things then maybe you could consider a single window app instead.

How do I show a new window after having closed the MainWindow?

I'm trying to do what is described in this post, display a log in window and when user successfully logs in, close it and open the main window of the application.
If the user logs on successfully, then I want to show the main window, if not, I want to exit the application
but the provided answers (at the time of posting this question) do not work for me since my code to show the windows is running from the App.cs.
I know the reason, its because the first window that starts up is automatically set to be the MainWindow of the application and when I call Close() on it, it exits the application. So the second window doesn't have a chance to open.
My question is how to overcome this? Or is this just not possible the way I described?
public partial class App : Application
{
public App(){}
private void Application_Startup(object sender, StartupEventArgs e)
{
LoginScreen f = new LoginScreen(); //becomes automatically set to application MainWindow
var result = f.ShowDialog(); //View contains a call to Close()
if (result == true) //at this point the LoginScreen is closed
{
MainWindow main = new MainWindow();
App.Current.MainWindow = main;
main.Show(); //no chance to show this, application exits
}
}
}
You can change application shutdown mode to OnExplicitShutdown and then call Application.Shutdown(0) whenever you want to. For example:
public App()
{
App.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
}
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
if (MessageBox.Show("Continue?", "", MessageBoxButton.YesNo) == MessageBoxResult.No)
App.Current.Shutdown(0);
}
Here in the constructor I'm changing application shudown mode and calling Shutdown method if I need to.
Caution: When you change ShutdownMode make sure to call Shutdown method otherwise your application will be in memory even after main window closes. I've overrided OnClosed method in my MainWindow to do that:
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
App.Current.Shutdown(0);
}
App.xaml : (In this file set the start window with the login view)
StartupUri="LoginWindow.xaml"
LoginWindow.xaml : (A file with a login window view)
LoginWindow.xaml.cs : (Code Behind for the view. Place here the function assigned to login. )
private void Login_Click(object sender, RoutedEventArgs e)
{
//Access control. If correct, go ahead. Here you must create a condition check
MainWindow main = new MainWindow();
main.Show();
this.Close();
}

OpenFileDialog doesn't work when in an Excel Add-In?

I've got an OpenFileDialog in a Windows Form which runs absolutely fine, howevever, when I want to do the same within an Excel Add-In, it does not seem to do anything. Below is an extract of my code, however I am struggling to see where the issue is as the code is identical for both (text box, openFileDialog and button names are identical).
public partial class DashboardControl : UserControl
{
public DashboardControl()
{
InitializeComponent();
}
private void DashboardControl_Load(object sender, EventArgs e)
{
}
private void fileLocationText_TextChanged(object sender, EventArgs e)
{
}
private void openFile_Click(object sender, EventArgs e)
{
openFileDialog1.ShowDialog();
}
private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
{
fileLocationText.Text = openFileDialog1.FileName;
}
}
Looks like the dialog is shown behind the Excel window. You need to set a parent window hanlde for the dialog ro bring it to the front. See SetForegroundWindow functin which brings the thread that created the specified window into the foreground and activates the window. Keyboard input is directed to the window, and various visual cues are changed for the user. The system assigns a slightly higher priority to the thread that created the foreground window than it does to other threads.
Note, the Show and ShowDialog methods of the System.Windows.Forms.Form class accepts an instance of the IWin32Window interface which allows to specify the parent window handle.

How to bring MainWindow into view when closing a window?

I'm trying to bring my MainWindow into view when I close a specific window within the same application. I have tried to do this but with the code I have created it just creates a new instance of MainWindow and I end up having 2 MainWindows instead of a desired one. Here is the code below that I have got.
private void Weight_Click(object sender, RoutedEventArgs e)
{
try
{
MultipleConverters.Windows.Weight WeightCalculation = new Windows.Weight();
WeightCalculation.Show();
this.WindowState = WindowState.Minimized;
}
// This code above works fine and minimizes the mainwindow and brings into view the selected window.
private void Quit_Click(object sender, RoutedEventArgs e)
{
this.Close();
MainWindow bringIntoView = new MainWindow();
bringIntoView.Show();
}
// Now with this code above is the problem code. This code is within the new window and what Iam trying to achieve is when this window is closed the mainwindow will be brought back into scope rather than creating a new instance of it, and leaving me with 2 Mainwindows rather than the desired 1 Mainwindow. any help would be great.
Use the Owner property to store the reference to the main window, you can then use that property to bring the window back up.
private void Weight_Click(object sender, RoutedEventArgs e)
{
try
{
MultipleConverters.Windows.Weight WeightCalculation = new Windows.Weight();
WeightCalculation.Owner = this;
WeightCalculation.Show();
this.WindowState = WindowState.Minimized;
}
elsewhere
private void Quit_Click(object sender, RoutedEventArgs e)
{
this.Close();
Owner.WindowState = WindowState.Normal;
}
However based on the behavior you are showing you may want to look in to using ShowDialog() instead of minimizing the parent window and use that instead.
private void Weight_Click(object sender, RoutedEventArgs e)
{
try
{
MultipleConverters.Windows.Weight WeightCalculation = new Windows.Weight();
WeightCalculation.Owner = this;
WeightCalculation.ShowDialog(); //The code pauses here till the dialog is closed.
}
Application.Current.MainWindow.Activate();
There is a handy property Application.Current.MainWindow that you can use to access the main window declared in App.xaml, you should just be able to show it by calling:
Application.Current.MainWindow.Show();
Application.Current.MainWindow.Activate();
To simplify things, you could create a static method on your MainWindow which handles all this:
public static void TryReveal()
{
var mainWindow = Application.Current.MainWindow;
if (mainWindow == null)
{
// The main window has probably been closed.
// This will stop .Show() and .Activate()
// from throwing an exception if the window is closed.
return;
}
if (mainWindow.WindowState == WindowState.Minimized)
{
mainWindow.WindowState = WindowState.Normal;
}
// Reveals if hidden
mainWindow.Show();
// Brings to foreground
mainWindow.Activate();
}
And then your other windows can just call MainWindow.TryReveal(). That way your windows don't need any reference to the main window as the static method handles it.
The best way you could handle this in WPF though is (I think) using a messaging implementation (eg. MVVM Light's Messaging system, or Caliburn.Micro's EventAggregator). Your MainWindow would subscribe to a "MainWindowViewStateMessage" or something like that (defined by you) and your other windows would pass it through the messaging system. The main window would intercept it and do the necessary work.
private void Quit_Click(object sender, RoutedEventArgs e)
{
this.Close();
MainWindow bringIntoView = new MainWindow();
bringIntoView.Show();
}
You're creating a new instance of MainWindow and then showing it. This is why a new MainForm is shown.
One thing you can do is set a property on the WeightCalculation window like this:
public MainWindow _mainWindow { get; set; }
Before showing the WeightCaculation, set _mainWindow to your current instance of MainWindow :
MultipleConverters.Windows.Weight WeightCalculation = new Windows.Weight();
WeightCalculation._mainWindow = this;
WeightCalculation.Show();
this.WindowState = WindowState.Minimized;
and from the new form you can now interact with the MainWindow.

Why I can't call 'new Window().ShowDialog()' 2 times in Application startup?

Here's the XAML code:
<Application x:Class="WpfApplication2.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="Application_Startup" />
Backing code:
using System.Windows;
namespace WpfApplication2
{
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
new Window().ShowDialog();
new Window().ShowDialog();
}
}
}
Window shows only one time and then application exits. Why??
UPDATE: I know that windows should show up consequently. But after I close first window second does not show up at all
Try this
private void Application_Startup(object sender, StartupEventArgs e)
{
var w1 = new Window();
var w2 = new Window();
w1.ShowDialog();
w2.ShowDialog();
}
Paste form comment:
I think when you close first window,application checks whether there are other windows,and it doesn't find any (so application is closing), because second window haven't been created
Am I right to say that this will show the two windows consecutively and not simultaneously? When window1 is closed window2 will automatically open as the call is ShowDialog() which opens the window and then sets focus to it and doesn't open the other one until window1 is closed?
You can use a for loop to do so. Howerver, I have no idea why can't call directly.
for (int i = 0; i < 2; i++)
{
new Window().ShowDialog();
}
You are possibly ending the entire application in the Code used to close Window 1. If you are using something like Environment.Exit(0); this could be the issue.
ShowDialog wont allow you to create a same form unless its closed.
It's the difference between a modal and modeless form.
I think WPF is as the same reason...
and you can see ↓
Display Modal and Modeless Windows Forms
UPDATE:
Take a test by Stecya's answer , and it work fine...
protected override void OnStartup(StartupEventArgs e)
{
var w1 = new Window();
var w2 = new Window();
w1.ShowDialog();
w2.ShowDialog();
}

Categories