How to stop a new window to be opened every time? - wpf

I have a WPF application in which on a click of a menu item a window is opened. If the same menu item is clicked again when the window is already open, it is opening a new window but I don't want a new window to be opened every time.
What I need is, if the window is already open, the same window should be focused not a new window.

//First we must create a object of type the new window we want the open.
NewWindowClass newWindow;
private void OpenNewWindow() {
//Check if the window wasn't created yet
if (newWindow == null)
{
//Instantiate the object and call the Open() method
newWindow= new NewWindowClass();
newWindow.Show();
//Add a event handler to set null our window object when it will be closed
newWindow.Closed += new EventHandler(newWindow_Closed);
}
//If the window was created and your window isn't active
//we call the method Activate to call the specific window to front
else if (newWindow != null && !newWindow.IsActive)
{
newWindow.Activate();
}
}
void newWindow_Closed(object sender, EventArgs e)
{
newWindow = null;
}
I think this solve your problem.
Att,

If your opened windows is used as simple dialog box you can use following code
window.ShowDialog();
when the dialog will show you cannot press any menu items unit you close this window

A rather brute force approach like this also works:
bool winTest = false;
foreach (Window w in Application.Current.Windows)
{
if (w is testWindow)
{
winTest = true;
w.Activate();
}
}
if (!winTest)
{
testWindow tw = new testWindow();
tw.Show();
}

You can create a field and check if it's set:
private Window _dialogue = null;
private void MaekWindowButton_Click(object sender, RoutedEventArgs e)
{
if (_dialogue == null)
{
Dialogue diag = new Dialogue();
_dialogue = diag;
diag.Closed += (s,_) => _dialogue = null; //Resets the field on close.
diag.Show();
}
else
{
_dialogue.Activate(); //Focuses window if it exists.
}
}

Related

Refresh or Close wpf window

I have a wpf window that shows Bing map whith som bushpin on it,
The window is getting opened by button click in code behind.
Each time i click on the button, new window shows up with current new data.
How can i close the "allready" opened window and open the a new one with the new data, or maybe refresh the current opened window with the new data.
here is my code:
IList<object> rowsToExport = getRows();
BingMapWindow window = new BingMapWindow(rowsToExport);
// somthing like this
if(window.IsOpened)
window.Close;
window.show();
OR
if(window.IsOpened)
window.refresh();
Have you considered storing reference to that window outside method and just checking it for null?
BingMapWindow window;
private void CloseWindow()
{
if(window != null)
{
window.Close();
window = null;
}
}
private void OpenWindow(BingMapWindow window)
{
this.window = window;
this.window.Show();
}
private void ButtonHandler()
{
CloseWindow();
var bingWindow = new BingMapWindow();
OpenWindow(bingWindow);
}

Custom MessageBox using Window

In regard to the code below.
If I use the built in MessageBox, then the previous MessageBox has to be closed before the next one is displayed.
How can I achieve this with a Window so that I can create a custom message box? I tried using the ShowDialog method, but whilst this does create Modal windows, it still shows them all at the same time cascaded.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
for (int i = 0; i < 3; ++i)
{
Dispatcher.BeginInvoke(new Action(() => ShowDialog2()));
}
}
void ShowDialog2()
{
//MessageBox.Show("A message");
Window w = new Window() { Width = 200, Height = 200, Content = "SomeText" };
w.ShowDialog();
}
}
Open first instance of window with ShowDialog and consequent instances of window with Show method.
Show open a non-modal window whereas ShowDialog open modal window.

How to ignore user clicks in WinForms?

When a user clicks a button, it starts some task. I don't want to block the main application thread, so I run it in a separate thread. Now I need to forbid a user to click the button until my task finishes.
I could set
button.Enabled = false;
, but I'm looking for some way to ignore clicks on it.
I could add some check in click event handler:
if (executingThread != null) return;
, but I will have to do it for each handler which is bad idea.
I know that there is some way to filter user's messages. Could you point me how to do this? And I don't want to filter out all messages, because some other buttons must stay clickable, I need to filter out messages that come to particular controls (buttons,grids and etc).
SOLUTION
internal class MessagesFilter: IMessageFilter
{
private readonly IntPtr ControlHandler;
private const int WM_KEYUP = 0x0101;
public MessagesFilter(IntPtr ControlHandler)
{
this.ControlHandler = ControlHandler;
}
#region IMessageFilter Members
public bool PreFilterMessage(ref Message m)
{
// TODO: Add MessagesFilter.PreFilterMessage implementation
if (m.Msg == WM_KEYUP)
{
if (m.HWnd == ControlHandler)
{
Keys k = ((Keys) ((int) m.WParam));
if (k == Keys.Enter)
return true;
}
}
return false;
}
#endregion
}
As always, the UI should be presented in such a way that user understands what the application is doing and should talk to the user with UI elements.
As Adam Houldsworth suggested I would also prefer keeping the button either disabled or enabled but I would also suggest that the caption of the button should convey the message to the user that the long processing is in progress when the new thread starts..and so the caption of the button should be immediately changed to something like "Processing..Please wait..." (in addition to being disabled or even if you want to keep it enabled), and then if you have kept the button enabled just check the caption of the button (or a isProcessing bool flag) on its click event to return if it says "Processing..Please wait..." or (isProcessing == true).
Lots of the Websites which help users to upload files/images change the Upload button's caption to "Uploading..Please wait..." to inform the user to wait until the upload finishes and additionally some sites also disable the upload button so that the user is not able to click again on Upload button.
You would need to also revert back the caption to normal when the thread finishes long processing.
There may be other advanced ways but the idea is to keep it as simple and basic as possible.
Look at this example on Threading in Windows Forms which shows to disable the button while multi-threading.
+1 for all the suggestions so far. As CSharpVJ suggests - My idea was to additionally inform the user by changing the button's caption making the UI design more intuitive
This can be achieved elegantly with Backgroundworker component in Winforms [No hassles code]. Just copy-paste and HIT F5 (After creating a New Winforms Project with a Button and a Label on it)!
You do not have to check anything related to button here. Everything will be taken care by the appropriate event handlers. its just that you have to do correct stuffs int he resepctive event handlers. Try it !
using System.ComponentModel;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form3 : Form
{
private BackgroundWorker _worker;
public Form3()
{
InitializeComponent();
InitWorker();
}
private void InitWorker()
{
if (_worker != null)
{
_worker.Dispose();
}
_worker = new BackgroundWorker
{
WorkerReportsProgress = true,
WorkerSupportsCancellation = true
};
_worker.DoWork += DoWork;
_worker.RunWorkerCompleted += RunWorkerCompleted;
_worker.ProgressChanged += ProgressChanged;
}
/// do time consuming work here...
void DoWork(object sender, DoWorkEventArgs e)
{
int highestPercentageReached = 0;
if (_worker.CancellationPending)
{
e.Cancel = true;
}
else
{
double i = 0.0d;
for (i = 0; i <= 199990000; i++)
{
// Report progress as a percentage of the total task.
var percentComplete = (int)(i / 199990000 * 100);
if (percentComplete > highestPercentageReached)
{
highestPercentageReached = percentComplete;
// Report UI abt the progress
_worker.ReportProgress(percentComplete);
_worker.CancelAsync();
}
}
}
}
void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
button1.Enabled = true;
if (e.Cancelled)
{
// Display some message to the user that task has been
// cancelled
label1.Text = "Cancelled the operation";
}
else if (e.Error != null)
{
// Do something with the error
}
button1.Text = "Start again";
}
void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text = string.Format("Result {0}: Percent {1}",e.UserState, e.ProgressPercentage);
}
private void OnStartClick(object sender, System.EventArgs e)
{
_worker.RunWorkerAsync();
button1.Text = "Processing started...";
button1.Enabled = false;
}
}
}
As mentioned in other answers, there is probably a better solution than what you are asking for.
To directly answer your question, check out the IMessageFilter interface
Create your filter to have it suppress the mouse messages you don't desire, apply it when necessary using Application.AddMessageFilter().
Something along these lines (this should probably compile...):
public class MouseButtonFilter : IMessageFilter
{
private const int WM_LBUTTONDOWN = 0x0201;
private const int WM_LBUTTONUP = 0x0202;
private const int WM_LBUTTONDBLCLK = 0x0203;
private const int WM_RBUTTONDOWN = 0x0204;
private const int WM_RBUTTONUP = 0x0205;
private const int WM_RBUTTONDBLCLK = 0x0206;
private const int WM_MBUTTONDOWN = 0x0207;
private const int WM_MBUTTONUP = 0x0208;
bool IMessageFilter.PreFilterMessage(ref Message m)
{
switch (m.Msg)
{
case WM_LBUTTONDOWN:
/* case ... (list them all here; i'm being lazy) */
case WM_MBUTTONUP:
return true;
}
return false;
}
}

Silverlight & C# - Open a childwindow only if a time frame passes

Hopefully the title makes sense but I will discribe my issue. I am using a childwindow in Silverlight to display a Processing message and rotating image when the UI is doing some work. Once a Completed Event is called, the window then closes.
Problem is that it does look a little ugly when the UI performs a quick task as the child window opens and then closes in under 1 second.
What I want to be able to do is have the child window open only if 2 seconds of processing has passed and then close on complete.
I have added a section of my xaml where I am calling the child below. I have searched but cannot find anything on this and it might not be possible.
void edit_Closed(object sender, EventArgs e)
{
EditChannelDetails edit = sender as EditChannelDetails;
if (edit.DialogResult == true)
{
if (edit != null)
{
Channel edited = new Channel();
edited.channelId = Int32.Parse(edit.ChannelID.Text);
edited.name = edit.ChannelName.Text;
edited.description = edit.ChannelDescription.Text;
ChannelClient proxy = new ChannelClient(new BasicHttpBinding(), new EndpointAddress("http://servername"));
proxy.UpdateChannelCompleted += new EventHandler<UpdateChannelCompletedEventArgs>(proxy_UpdateChannelCompleted);
proxy.UpdateChannelAsync(edited);
}
}
processingDialog.Show();
}
void proxy_UpdateChannelCompleted(object sender, UpdateChannelCompletedEventArgs e)
{
processingDialog.Close();
Etc.....
Boolean closeFlag = false;
Start a timer:
DispatcherTimer timer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(2) };
timer.Tick += (tts, tte) => {
timer.Stop();
closeFlag = true;
};
timer.Start();
And check flag:
if (!closeFlag)
{
processingDialog.Close();
}

How to handle dialogs with multiple buttons in WPF?

I have a Window with seven buttons; I use it as a menu in a simple game I am working on, but I display it as a dialog. How can I know which button user has pressed, since DialogResult in WPF only offers true, false and null?
If you're making a custom Window in this way, you don't really need to worry about DialogResult.
You can keep track of this in a property within your Window, and just read the property after the dialog is closed.
MyDialog window = new MyDialog();
if (window.ShowDialog() == false)
{
// user closed the window...
}
var choice = window.CustomPropertyContainingChoice;
Define your own enum and offer a static method to display the window that return your enum.
The code below does the same thing it is part of a window that allows users to review their changes and accept or cancel. As I only need true and false I used a bool however it would be trivial to change to an enum.
public static bool DisplayChanges(List<INormalizedMessage> LstMessages)
{
var retlist = LstMessages.Where(( INormalizedMessage NM ) => { return NM.Status != NormalizedMessageStatus.NoChange; });
ReviewChanges RC = new ReviewChanges();
RC.Messages = retlist.ToList();
RC.ShowDialog();
return RC.Result;
}
private void cmdCancle_Click( object sender, RoutedEventArgs e )
{
Result = false;
Hide();
}
private void cmdOK_Click( object sender, RoutedEventArgs e )
{
Result = true;
Hide();
}

Resources