UI not getting updated after call to OpenFileDialog.ShowDialog() - c#

I have a WPF Application consisting of a MainWindow which also has a regular button inside.
Bound to the button click event I am loading a serialized object via OpenFileDialog:
private void LoadNetwork_Click(object sender, RoutedEventArgs e)
{
var openDialog = new OpenFileDialog { Multiselect = false };
var result = openDialog.ShowDialog();
if (result)
{
string file = openDialog.FileName;
try
{
_network= new SimplifiedNetwork(file, 1);
MessageBox.Show("Loaded OK");
}
catch (Exception)
{
MessageBox.Show("Load error");
}
}
}
After this method gets executed the UI doesn't update anymore. And when I say nothing, I mean not even the hover effects on the buttons in the Window work (not to mention updating labels via code behind, property changed events, begin invokes etc.), it's like it's frozen (but still responsive to clicks).
I thought it was something I did inside my routines, but simply reducing the method call to
private void LoadNetwork_Click(object sender, RoutedEventArgs e)
{
var openDialog = new OpenFileDialog { Multiselect = false };
var result = openDialog.ShowDialog();
}
has the same result.
Clarification.
-This occurs with after the Modal dialog is closed.
-It also seems to manifest itself as soon as the UI loses focus for any reason (like minimize - restore, switch to another window).
-This seems to occur only on my Windows 8.1 machine (put in an xp VM I have around, is OK).
Any ideas?

The OpenFileDialog is a modal dialog, it is intended that the window in the background is not responding when the dialog is open.
Here is more information and also a possible solution to your problem.

Related

Show MessageBox immediately in Windows Forms?

Is there any way to have a messagebox immediately pop up when a form opens? I just want to display a short message about how to use the form when it opens. I tried
private void myForm_Load(object sender, EventArgs e)
{
DialogResult dialogOpen = MessageBox.Show("Use the navigation menu to get started.", "Welcome!", MessageBoxButtons.OK);
}
but it doesn't work.
Showing a MessageBox during Form_Load works just fine for me. I literally copy/pasted the code from your original post, and it worked. I'm on .NET Framework 4.5 on Windows 8.1.
Are you sure your Load event handler is getting called? Perhaps the it's not hooked up to the Load event properly.
I don't see why it wouldn't work in Form_Load. Definitely try doing as others have pointed out by putting it beneath form initialization.
Though, given that you're just showing a message box, I don't think there is any reason to store the result, so a simple MessageBox.Show(message); Should do the trick.
As #s.m. said, from a UX point of view, having a notification thrown in your face as soon as the app starts would be very obnoxious, at least if you have it EVERY time. Personally, I would create a boolean Settings variable, set it to true the first time the message is displayed, and only display it when the setting is false, i.e. the first time the message is displayed.
private boolean splashShown = Properties.Settings.Default.splashShown;
private void Form_Load(object sender, EventArgs e)
{
if (!splashShown)
{
MessageBox.Show("message");
myForm.Properties.Settings.Default.splashShown = true;
myForm.Properties.Settings.Default.Save();
}
}
And set up the splashShown Setting in your form properties.
If the problem is that your Form_Load() method isn't actually attached to your Form.Load() event, you can double click the form window in the designer and it will automatically created the Form_Load() base method for you and attach it to the Form.Load() event
Is there a reason to use the Load method of the form? If not you could to it in the constructor of form. If you want it to show up immediately after your form loads, you should do it in the constructor after the form is initialized. It should look something like this:
public partial class myForm : Form
{
public myForm()
{
InitializeComponent();
DialogResult dialogOpen = MessageBox.Show("Use the navigation menu to get started.", "Welcome!", MessageBoxButtons.OK);
}
}
The constructor (public myForm()) and the InitializeComponent(); should be automatically added to the form by Visual Studio after creating it.
Form_Load event occurs before the form is really visible.
I use:
static private bool splashShown = false;
private void Form1_Activated(object sender, System.EventArgs e)
{
if (!splashShown)
{
MessageBox.Show("message");
splashShown = true;
}
}
I have used this and it works fine. App start brings up messagebox first before all else.
InitializeComponent();
MessageBox.Show("put your message here");

Save document immediately after opening program

Please help, I am trying to make program as soon as it opens to prompt with window to save rtf file, I try to use Window_Activated event but when programs starts, it does open window to save as but it doesn't matter if i press on Save or Cancel, the SaveFileDialog keeps showing up in loop and can not get pass that. This is code I used but maybe is not even good.
private void Window_Activated(object sender, EventArgs e)
{
Microsoft.Win32.SaveFileDialog saveDlg = new Microsoft.Win32.SaveFileDialog();
saveDlg.DefaultExt = ".rtf";
saveDlg.Filter = "RTF Documents (.rtf)|*rtf";
Nullable<bool> rezultat = saveDlg.ShowDialog();
if (rezultat == true)
{
string filename = saveDlg.FileName;
System.IO.File.Create(filename);
}
}
Do it like this
*> NOTE: this will used goto statement where other may argued not to
used it but it is still supported and must only be used if no other
options*
private void Window_Load(object sender, EventArgs e)
{
System.Windows.Forms.SaveFileDialog saveDlg = new System.Windows.Forms.SaveFileDialog();
saveDlg.DefaultExt = ".rtf";
saveDlg.Filter = "RTF Documents (.rtf)|*rtf";
RetHere:
if (saveDlg.ShowDialog() == System.Windows.Forms.DialogResult.Yes)
{
string filename = saveDlg.FileName;
System.IO.File.Create(filename);
}
else {
System.Windows.Forms.MessageBox.Show("Your message here!", "Save", System.Windows.Forms.MessageBoxButtons.OK);
goto RetHere;
}
}
Window activated occurs when it becomes the foreground window, when you prompt the user to save, it changes focus, on clicking OK or CANCEL it changes back the focus to the main window, firing up the Window_Activated event. Could this be an infinite loop? I didn't test it but I guess it could happen.
Edit: I would suggest yout to use another event, maybe when the form loads?
You can't use Window_Activated for this (clearly). It's fired every time the window is activated. Here's what's happening:
Your app starts.
Window_Activated is executed.
You display the saveDlg, which deactivates your window.
The saveDlg closes, which activates your window.
Go to step #2
You need to either add a flag that is set the first time Window_Activated is executed, and check for it before executing the code, or use a different event that only runs once (like Load).

Can I stop a custom Excel task pane from being closed, moved, or resized by a user?

I'm creating a custom task panel for an Excel Add-In using VS 2010. I want the task pane to always be visible to the user, so it can't be closed, moved, or resized.
Is there a way to disable those capabilities in the task pane's title bar? Perhaps by disabling the close box and the down arrow button in the upper right corner?
Thanks
To stop a custom task pane from being closed:
When a user presses the close button, the result is that the custom pane's Visible property is set to false. This causes the custom pane's VisibleChanged event to fire. Within that event's handler, you can forcibly reopen the custom task pane.
private static void OnVisibleChanged(object sender, EventArgs e)
{
var customTaskPane = sender as CustomTaskPane;
if (customTaskPane != null)
{
Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => { customTaskPane.Visible = true; }));
}
}
Note that I'm using the Dispatcher's BeginInvoke method. This is because if you try to directly set the custom pane's Visible property to true, without using the Dispatcher, an exception is thrown since that isn't allowed within the event handler. Using the BeginInvoke method causes the assignment to execute asynchronously, thus working around that limitation.
To stop a custom task pane from being resized:
To accomplish this, you need to attach a SizeChanged event handler to the custom task pane's UserControl. For example:
var sampleHostControl = new WpfHostControl(Globals.AddIn.SamplePaneWpfControl);
_samplePane = this.CustomTaskPanes.Add(sampleHostControl, "Sample");
sampleHostControl.SizeChanged += new EventHandler(OnHostControlSizeChanged);
Inside the event handler, you can reset the _samplePane's height.
private const int PaneHeight = 52;
private void OnHostControlSizeChanged(object sender, EventArgs e)
{
if (_samplePane != null && _samplePane.Height != PaneHeight)
{
System.Windows.Forms.SendKeys.Send("{ESC}");
_samplePane.Height = PaneHeight;
}
}
The use of SendKeys.Send comes from this msdn forum post. A Microsoft Moderator indicates that SendKeys.Send stops the re-sizing operation. The Height comparison in the if-statement ensures that we only prevent vertical height changes; if a user wants to horizontally expand or shrink Excel, we shouldn't prevent that.
You can specify the Docking of your task pane and lock it so that its position cannot be modified by the user this way:
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
var taskPaneContainer = new TaskPaneContainer();
var taskPane = this.CustomTaskPanes.Add(taskPaneContainer, "My Task Pane");
taskPane.DockPosition = MsoCTPDockPosition.msoCTPDockPositionRight;
taskPane.DockPositionRestrict = MsoCTPDockPositionRestrict.msoCTPDockPositionRestrictNoChange;
taskPane.Visible = true;
}
On the other hand, as far as I know, it is not possible to directly prevent a user from making the TaskPane invisible. Your best bet is probably to add a button in the Ribbon to make the TaskPane visible again.

WinForms Form won't close on pressing X or Close() in C#

I'm having a bit weird problem with WinForm which seems to refuse to close for some weird reason. I've got very simple gui which sometimes doesn't react for me pressing X or when i use events on buttons it even reaches Close() and does nothing..
private void buttonZapisz_Click(object sender, EventArgs e) {
string plik = textBoxDokumentDoZaladowania.Text;
if (File.Exists(plik)) {
string extension = Path.GetExtension(plik);
string nazwaPliku = Path.GetFileName(plik);
SqlMethods.databaseFilePut(plik, comboBoxTypDokumentu.Text, textBoxKomentarz.Text, sKlienciID, sPortfelID, extension, nazwaPliku);
Close();
}
}
There are no events assigned to FormClosed or FormClosing. So how can I find out what's wrong. Sometimes X will work after the GUI is loaded but after i press Button to save some stuff to database it reaches Close() in that button event and it still is visible and does nothing. Can't use X, nor ALT+F4. I can go around GUI and choose other values for ComboBox without problem.
I call GUI like this:
private void contextMenuDokumentyDodaj_Click(object sender, EventArgs e) {
var lv = (ListView) contextMenuDokumenty.SourceControl;
string varPortfelID = Locale.ustalDaneListViewKolumny(listViewNumeryUmow, 0);
string varKlienciID = Locale.ustalDaneListViewKolumny(listViewKlienci, 0);
if (lv == listViewDokumentyPerKlient) {
if (varKlienciID != "") {
var dokumenty = new DocumentsGui(varKlienciID);
dokumenty.Show();
dokumenty.FormClosed += varDocumentsGuiKlienci_FormClosed;
}
} else if (lv == listViewDokumentyPerPortfel) {
if (varPortfelID != "" && varKlienciID != "") {
var dokumenty = new DocumentsGui(varKlienciID, varPortfelID);
dokumenty.Show();
dokumenty.FormClosed += varDocumentsGuiPortfele_FormClosed;
}
}
}
While I can't close GUI i can work on the main gui without problem too. I can open up same GUI and after opening new GUI i can quickly close it. GUI is very simple with few ComboBoxes,TextBoxes and one EditButton from Devexpress.
Edit: varDocumentsGuiPortfele_FormClosed code allows me to refresh GUI (reload ListView's depending on where the user is on now).
private void varDocumentsGuiPortfele_FormClosed(object sender, FormClosedEventArgs e) {
TabControl varTabControl = tabControlKlientPortfele;
if (varTabControl.TabPages.IndexOf(tabPageDokumentyPerKlient) == varTabControl.SelectedIndex) {
loadTabControlKlientPortfeleBezZmianyUmowy();
}
}
Paste this code into your form classes:
protected override void OnFormClosing(FormClosingEventArgs e) {
e.Cancel = false;
base.OnFormClosing(e);
}
When that works, you want to find out why you have Validating event handlers that don't want the form to be closed.
Next thing you want to verify is Debug + Exceptions, tick the Thrown box for CLR Exceptions. This makes sure you don't swallow an exception that prevents a form from closing. Or worse, the operating system swallowing the exception, a nasty Windows 7 problem.
If you are getting an Exception in your close method, then the Base closing method is never called.
Put a try{}catch{} around everything

When to make a form flash and stop flashing?

I am writing an IM program, and I have the method to make a form flash and stop flashing... question is, how do I implement it?
When a message arrives, I can set the window flashing, but I need to make sure it doesn't have focus. Checking the focued method always seems to return false and so it flashes even when the form is open.
Also, which event to I need to handle to stop it flashing? When the user clicks the form to make it maximise, or switches focus to the form, I need a way of stopping it.
What's the best way?
You can handle the Activated and Deactivate events of your Form, and use them to change a Form-level boolean that will tell your code whether your form has the focus or not, like this:
private bool _IsActivated = false;
private void Form1_Activated(object sender, EventArgs e)
{
_IsActivated = true;
// turn off flashing, if necessary
}
private void Form1_Deactivate(object sender, EventArgs e)
{
_IsActivated = false;
}
When a message arrives, you check _IsActivated to determine if your Form is already the active window, and turn on flashing if it isn't. In the Activated event, you would turn off the flashing if it's on.
The Focused property of your form will always return false if it has any controls on it. This property refers to whether the control in question (the form, in this case) has the focus within your application's form, not whether the application itself has the focus within Windows.
Checking if the form is minimized or not:
if (this.WindowState == FormWindowState.Minimized)
{
MakeFormFlash();
}
else
{
MakeFormStopFlash();
}
Event to trigger when the form is activated by user or code:
this.Activated += new EventHandler(Form_Activated);
Well Focused should be the property to check, so you need to try and work out why that is always returning false.
As for what event to listen to, probably the GotFocus event, though that may not work until you can work out what is wrong with the Focused property.
There are a number of ways you can handle this. Probably the easiest would be to have a flag that you set whenever the form is flashing so this can be reset on re-activation of the form e.g.
Code for base IM window form
private bool IsFlashing;
....
// Code for IM windows
public void OnActivate(EventArgs e)
{
if (IsFlashing)
{
// stop flash
IsFlashing = false;
}
}
public void Flash()
{
// make flash
IsFlashing = true;
}
Then wherever you do your code to handle the new message you would just need to check that the particular conversation window (if you handle multiple ones) that the message is directed at is the current active one:
public void OnNewMessage(AMessage msg)
{
Form convoWindow = FindConvoWindow(msg.Sender);
if (Form.ActiveForm == convoWindow)
{
// update the conversation text
}
else
{
convoWindow.Flash();
}
}

Categories

Resources