I am new to WPF, and my application uses several dialogs. Each of the dialogs currently looks like this:
public partial class EditTeamDialog : Window {
public EditTeamDialog() {
InitializeComponent();
Loaded += (sender, args) => MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
}
private void OkButton_Click(object sender, RoutedEventArgs e) {
DialogResult = true;
}
}
The Loaded += line and the Click method both seem to me so common behavior that I expect them to be provided by WPF. It shouldn’t be necessary for every programmer of a dialog window to write this code.
How can I achieve the same behavior (dialog focuses first element on startup, closes on Enter) with writing less code?
Related
I want to be able to press a button and have the program open up a new window and close the old one.
I have followed solutions from this link but i have never has success with any of them How do I open a second window from the first window in WPF?
Here is my work soo far:
Window editor = new Window();
editor.Show();
this.Close();
But this does nothing.
The program should open up a new window and close the old one.
The functionality you described will work just fine. The Problem there is would more likely be the function or Methode in which you call this function.
To write a Methode that would handle a Button press as you want is pretty good described here: https://www.c-sharpcorner.com/forums/c-sharp-button-click-hold-and-release.
Hopefully, this will help you otherwise just ask
here is a small Implementation if that helps:
public partial class MainWindow : Window
{
private void MainWindow_KeyDown(object sender, KeyEventArgs e)
{
Window editor = new MainWindow();
editor.Show();
this.Close();
}
private void MainWindow_KeyUP(object sender, KeyEventArgs e)
{
}
public MainWindow()
{
this.KeyDown += MainWindow_KeyDown;
this.KeyUp += MainWindow_KeyUP;
}
}
You have to call the second window from the first. This is something I did for a project where it popped up a new login panel window:
private void displayLoginPanel_Click(object sender, EventArgs e)
{
LoginPanel myLogin = new LoginPanel(this);
myLogin.Show();
this.Hide();
}
I used hide() instead of close() because you can see that I am sending a reference of the parent to the child LoginPanel in order to come back later. You can replace the Hide() with Close().
Is this possible to detect a mouse click (Left/Right) anywhere (Inside and Outside the Form) in an if statement? And if it's possible, how?
if(MouseButtons.LeftButton == MouseButtonState.Pressed){
...
}
Here is a starter, if I understood your needs of "clicking from outside the window" and Hans Passant's suggestion doesn't fit your needs. You might need to add an event handler for Form1_Click.
CAUTION: This code is provided to illustrate the concept. The threading synchronization in this sample is not 100% correct. Check the history of this answer for an attempt at a more "threading correct" one that sometimes throws exceptions. As an alternative, to get rid of all threading issues, you could have the task in StartWaitingForClickFromOutside be instead always running (aka be always in "listen" mode) as opposed to trying to detect the "within the form" or "outside the form" states and starting/stopping the loop accordingly.
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.MouseLeave += Form1_MouseLeave;
this.Leave += Form1_Leave;
this.Deactivate += Form1_Deactivate;
this.MouseEnter += Form1_MouseEnter;
this.Activated += Form1_Activated;
this.Enter += Form1_Enter;
this.VisibleChanged += Form1_VisibleChanged;
}
private AutoResetEvent are = new AutoResetEvent(false);
// You could create just one handler, but this is to show what you need to link to
private void Form1_MouseLeave(object sender, EventArgs e) => StartWaitingForClickFromOutside();
private void Form1_Leave(object sender, EventArgs e) => StartWaitingForClickFromOutside();
private void Form1_Deactivate(object sender, EventArgs e) => StartWaitingForClickFromOutside();
private void StartWaitingForClickFromOutside()
{
are.Reset();
var ctx = new SynchronizationContext();
var task = Task.Run(() =>
{
while (true)
{
if (are.WaitOne(1)) break;
if (MouseButtons == MouseButtons.Left)
{
ctx.Send(CLickFromOutside, null);
// You might need to put in a delay here and not break depending on what you want to accomplish
break;
}
}
});
}
private void CLickFromOutside(object state) => MessageBox.Show("Clicked from outside of the window");
private void Form1_MouseEnter(object sender, EventArgs e) => are.Set();
private void Form1_Activated(object sender, EventArgs e) => are.Set();
private void Form1_Enter(object sender, EventArgs e) => are.Set();
private void Form1_VisibleChanged(object sender, EventArgs e)
{
if (Visible) are.Set();
else StartWaitingForClickFromOutside();
}
}
}
If I understood you incorrectly, you might find this useful: Pass click event of child control to the parent control
When user clicks outside the form control, it losses the focus and you can make use of that.which means you have to use the _Deactivate(object sender, EventArgs e) event of the form control to make this work. Since which will trigger when the form loses focus and is no longer the active form. Let Form1 be the form, then the event will be like the following:
private void Form1_Deactivate(object sender, EventArgs e)
{
// Your code here to handle this event
}
One method is to cover the entire screen with a borderless form with the properties set to transparent (a few percent above completely transparent, not sure if total transparency works but you won't notice the difference) and also set to topmost. Then use the events from the form. As soon as a click is detected this will not affect anything underneath the form (which in my application is something I want to happen) but the form could be closed and another mouse click simulated a fraction of a second later to activate the controls that are underneath. I had no problem using the windows API to use mouse hooks in VB6 but cannot seem to find something that works in c# with the 2019 version of .NET so this is a good workaround. Of course to be really clever you could use an irregular forms method to make the transparent form the same shape as the mouse and follow it.
Note: I have just found the complete code to do it using hooks that mere mortals can get up and running at once! KeyboardMouseHooks C# Library - CodePlex Archive
PS if you use my (dumb) method remember to create an escape key or button or you will have to restart your computer unless the form is programmed to disappear for real clicks as suggested!
I know this is late but maybe it helps someone. Using the MouseEventArgs of the MouseUp event of any control you can check for mouse button and wheel among other things. Here is an example.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.MouseUp += Form1_MouseUp;
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
{
DoSomething_LeftClick();
}
else if(e.Button == MouseButtons.Right)
{
DoSomething_RightClick();
}
}
private void DoSomething_LeftClick()
{
//Here some code
}
private void DoSomething_RightClick()
{
//Here some code
}
}
The issue I am having and looks like many people have had in the past when
dealing with WPF is I want to either hide or close the MainWindow of the
application when a new Window is open. The reason I want to do this is because making tabs for it doesn't look neat to me, especially with how I designed my UI. I have tried using newWindow.Show() and oldWindow.Close(), however when the program runs, the oldWindow is still being shown when it should have been closed. I have also tried making it so the oldWindow is hidden when the newWindow has been called. They both produce the exact same results. As I understand it, You cannot actually close the MainWindow because it is needed for the program to continue to run. So, I know I want to go the route of hiding the MainWindow, but as you can see with my question, it isn't working as intended.
Can anyone possibly explain what I am doing wrong or give pointers for an
alternative method I could go with?
namespace WorkinProgress
{
/// <summary>
/// Interaction logic for EnglishLanguageSelection.xaml
/// </summary>
public partial class EnglishLanguageSelection : Page
{
public EnglishLanguageSelection()
{
InitializeComponent();
loadList();
}
private void loadList()
{
listBox.Items.Add("math");
listBox.Items.Add("science");
listBox.Items.Add("history");
listBox.Items.Add("english");
}
private void listBox_SelectionChanged(object sender,
SelectionChangedEventArgs e)
{
if (listBox.SelectedIndex == 1)
{
MainWindow main = new MainWindow();
ScienceWindow sci = new ScienceWindow();
NavigationService.Navigate(sci);
main.Close();
}
}
}
}
I have also tried changing the event handler to:
private void listBox_SelectionChanged(object sender,
SelectionChangedEventArgs e)
{
if (listBox.SelectedIndex == 1)
{
MainWindow main = new MainWindow();
ScienceWindow sci = new ScienceWindow();
sci.Show();
main.Visibility = System.Windows.Visibility.Hidden;
}
}
You cannot actually close the MainWindow because it is needed for the
program to continue to run
This assertion is wrong, although it is the default behavior, you can set the ShutdownMode of the Application class to either OnLastWindowClose or OnExplicitShutdown. Then closing the main window won't end your application.
Also, you might want to use the Hide method instead of Close since it seems that you want to restore the main window later.
About the code you posted, I don't quite understand what you're doing. You're creating a new MainWindow and closing it just after, instead of attempting to close the already existing MainWindow.
You seems to be using pages - Are you sure you really want to create new windows, and not simply navigate between different pages on the same window?
Anyway, here is a possible implementation of your method that should work:
private void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (listBox.SelectedIndex == 1)
{
ScienceWindow sci = new ScienceWindow();
sci.Show();
// Note: Better store the main window in a globally accessible place
// since you want to retrieve it once it is hidden to show it again
var main = Window.GetWindow(this);
main.Hide();
}
}
And in App.xaml.cs:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
ShutdownMode = ShutdownMode.OnLastWindowClose;
}
I'm a beginner and having some dicciculties with XAML.
I have a main view A, which has a button to open a pop-up-window B. When this happens, Window A should still be visible and openened, but disabled. I've done this in code behind (maybe not the cleanest way, but the only way I know how). The code i used for this is the following:
//Code behind from view A
private void X-Button_Click(object sender, RoutedEventArgs e)
{
var BWindow = new BView();
BWindow.Show();
this.IsEnabled = false;
}
I would like to get window A enabled again once i close window B, but i can t seem to get this work. Any help would be very much appreciated.
You could do it in the following way.
You register yourself on the Closed event of the window, and when it gets closed, you unregister the event, and re-enable the this form.
private void Button_Click(object sender, RoutedEventArgs e)
{
Window BWindow = new BWindow();
BWindow.Show();
BWindow.Closed += BWindow_Closed;
this.IsEnabled = false;
}
void BWindow_Closed(object sender, EventArgs e)
{
Window win = sender as Window;
if (win != null)
{
win.Closed -= BWindow_Closed;
}
this.IsEnabled = true;
}
I assume you are looking for modal window. See similar question asked here: How do make modal dialog in WPF?
The solution is in using ShowDialog method from Window class. See here for reference:
http://msdn.microsoft.com/en-us/library/system.windows.window.showdialog.aspx
Modal window is the concept when you open new window B from the existing window A. While the B is open, the A is disabled and cannot be used. Window A become active only when the B is closed.
...in Silverlight. No tags in the title, and all that. I'm using Silverlight 4 on Chrome, though I've tried it on IE too. I've tried:
System.Windows.Browser.HtmlPage.Plugin.Focus();
this.Focus();
Dispatcher.BeginInvoke(() => { textBox_username.Focus(); });
And various combinations thereof (as suggested by a similar thread), as well as a separate method that was attached to the form loaded event. The above gets me the closest, since clicking anywhere on the page gives my textbox focus, like the plugin isn't getting focus still. Could be because this is the first window viewed?
I dont think that was because the first window viewed. try to put this.Focus(); after your Dispatcher you set it false;
Change your code similar to below
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
this.Loaded += MainPage_Loaded;
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
System.Windows.Browser.HtmlPage.Plugin.Focus();
txtBox.UpdateLayout();
txtBox.Focus();
}
}