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.
Related
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.
So, I'm making a payroll management system as a hobby project to help my resume and general knowledge of c#. So, I'm making a UI and I can open a new window just fine with this code:
private void button1_Click(object sender, EventArgs e)
{
CreateAdminAcct createAcct = new CreateAdminAcct();
createAcct.StartPosition = FormStartPosition.CenterScreen;
createAcct.Show();
this.Hide();
}
however, I don't know the event to check when the little red "x" button is clicked, because when that button is clicked, I want to go back to the main screen because I hide the main screen when that button is clicked, and when i click the red "x" on the screen that just opened, it closes, but the application continues to run in the background.
If there is some better way to manage multiple menus, I'm open to suggestions, however, this is what I've found easiest.
Thanks in advance
I second Robert Harvey's suggestion; this gives the user the reassurance tha tht emain window is still open/ nothing got lost, but it's unreachably "behind" the CreateAdminAcct form while the CreateAdminAcct form is open
private void button1_Click(object sender, EventArgs e)
{
CreateAdminAcct createAcct = new CreateAdminAcct();
createAcct.StartPosition = FormStartPosition.CenterScreen;
createAcct.ShowDialog();
//do any code here that needs to access createAcct before it's lost
MessageBox.Show(createAcct.NewAdmin.Name);
}
If you really do want to hide your main form, pass the main form itself to createAcct, and make it createAcct's job to re-open the main form when it is closing
private void button1_Click(object sender, EventArgs e)
{
CreateAdminAcct createAcct = new CreateAdminAcct(this); //note passing this form to constructor
createAcct.StartPosition = FormStartPosition.CenterScreen;
createAcct.Show();
}
class CreateAcctForm : Form{
private Form _showWhenClosing;
CreateAcctForm(Form revertTo){
InitializeComponent();
_showWhenClosing = revertTo;
}
}
void Form_Closing(object sender, ...){ //event
_showWhenClosing.Show();
}
Side note: please rename your controls after you drop them ona form. code that's stuffed with label57, textbox25 is effectively obfuscated and really wearisome to follow
I'm building a GUI application with C# and gtk#. I've encountered an issue recently and was looking for the best solution to this problem:
I have a modal window that pops up for the user to enter a number. This window is a separate window accessed from my main window and it's set up like this:
public class MainWindow()
{
public NumberEntry numEntry;
Whenever I need numerical input from the user, I call ShowAll() on the public Window property of NumberEntry like:
numEntry.win.ShowAll();
And all of this works fine. Afterwards, to get the value they entered, I call:
int entered = numEntry.valueEntered;
The issue is obviously that code continues executing immediately after the ShowAll() line is finished, and numEntry.valueEntered is always 0. What I'd like to do (and have been trying to do), is to suspend the main thread, and open up the number entry window in a second thread, and join back to the main thread when this is complete. Suspending the main thread seems to prevent GUI changes making the program freeze when I try to open the number entry window. I'd also like to avoid callback methods if at all possible, seeing as how this would get rather complicated after awhile. Any advice? Thanks!
Seems like when GTK window is closed all its child controls are cleared. So to get the result from the custom dialog window you may do the following (I am not gtk guru but its works for me):
1. Create a new dialog window with your controls (I used Xamarin studio). Add result properties, OK and Cancel handlers and override OnDeleteEvent method:
public partial class MyDialog : Gtk.Dialog
{
public string Results {
get;
private set;
}
public MyDialog ()
{
this.Build ();
}
protected override bool OnDeleteEvent (Gdk.Event evnt)
{
Results = entry2.Text; // if user pressed on X button..
return base.OnDeleteEvent (evnt);
}
protected void OnButtonOkClicked (object sender, EventArgs e)
{
Results = entry2.Text;
Destroy ();
}
protected void OnButtonCancelClicked (object sender, EventArgs e)
{
Results = string.Empty;
Destroy ();
}
}
2. In your main window create a dialog object and attach to its Destroyed event your event handler:
protected void OnButtonClicked (object sender, EventArgs e)
{
var dialog = new MyDialog ();
dialog.Destroyed += HandleClose;
}
3. Get the results when dialog is closed:
void HandleClose (object sender, EventArgs e)
{
var dialog = sender as MyDialog;
var textResult = dialog.Results;
}
If you whant you also may specify a dialog result property and etс.
I have a VSTO Project (WinWord addin) using c#.
The Project has only one window, it must be showed when click on some button, the problem is that it only happens when i'm debuging, if i try to use it after run the installation, it doesn't show the window. Here is my ribbon code:
public partial class MyRibbon
{
private void MyRibbon_Load(object sender, RibbonUIEventArgs e)
{
}
private void btnPublicar_Click(object sender, RibbonControlEventArgs e)
{
MyForm form = new MyForm();
//form.TopLevel = true;
form.ShowDialog();
//form.Show();
}
private void gallery1_Click(object sender, RibbonControlEventArgs e)
{
}
private void editBox1_TextChanged(object sender, RibbonControlEventArgs e)
{
}
}
The commented code are some tries. Any help tks.
After very deep debug, found my addin were throwing an non handeled exception (some XML files needed by addin are lost. They weren't where they should), the extrange thing is that Word doesn't show the problem, simply doesn´t open the form.
I have a strange bug, please, let me know if you have any clues about the reason.
I have a Timer (System.Windows.Forms.Timer) on my main form, which fires some updates, which also eventually update the main form UI. Then I have an editor, which is opened from the main form using the ShowDialog() method. On this editor I have a PropertyGrid (System.Windows.Forms.PropertyGrid).
I am unable to reproduce it everytime, but pretty often, when I use dropdowns on that property grid in editor it gets stuck, that is OK/Cancel buttons don't close the form, property grid becomes not usable, Close button in the form header doesn't work.
There are no exceptions in the background, and if I break the process I see that the app is doing some calculations related to the updates I mentioned in the beginning.
What can you recommend? Any ideas are welcome.
What's happening is that the thread timer's Tick method doesn't execute on a different thread, so it's locking everything else until it's done. I made a test winforms app that had a timer and 2 buttons on it whose events did this:
private void timer1_Tick(object sender, EventArgs e)
{
Thread.Sleep(6000);
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Start();
}
private void button2_Click(object sender, EventArgs e)
{
frmShow show = new frmShow();
show.ShowDialog(); // frmShow just has some controls on it to fiddle with
}
and indeed it blocked as you described. The following solved it:
private void timer1_Tick(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(DoStuff);
}
private void DoStuff(object something)
{
Thread.Sleep(6000);
}