Wpf usercontrol lost focus event or muse down beyond my control - c#

do you know a "simple" way to detect when a user control loses focus?
I am creating a console output inspired by Visual Studio.
Visual Studio console output collapses when I click anywhere.
Obviously in my application if I click on a Panel (which has no focus) I do not receive any events.
I had thought about using the mouse_down event on the application, but I would have to do an evaluation with every click!
Do you know any way to know when you click out of your control?

UserControl has a LostFocus event. In the code behind of your UserControl you can simply add an event handler.
public partial class MainView : UserControl
{
public MainView()
{
InitializeComponent();
LostFocus += OnFocusLost;
}
private void OnFocusLost(object sender, RoutedEventArgs e)
{
// Do something here.
}
}
If you are referencing it from another class then you can create an event handler on that class and subscribe to the event from the UserControl.
UserControl control = new UserControl();
control.LostFocus += OnFocusLost;
With that being said, if you have a TextBox or some other control inside of the UserControl then the UserControl will lose focus every time a TextBox gets the focus so you will most likely need to write a method to determine if any of the elements inside the UserControl have focus.

Related

C# Click event for multiple controls inside custom control

I'm trying to make a custom User Control with multiple controls inside (for this example, a Picture box and a label) and I want them all to respond to the same event that I make on the form where I'm using it, all th objects would be:
UserControl1
pictureBox1
label1
However, when i make the (click) event on the form where I wanna use (Form1) the event only applies to the background (userCoontrol1), and therefore it will not work if I click the Picturebox or label, how could I make it that the event applies to every control inside?
I have tried making a click event for userControl1 and applying the same to the others and that works, but I need to change the behavior from the parent which is why this doesn't work, and I'm not sure how I can override this.
Taking into account your comment... One method might be the following
link click event of usercontrol to form1, in form1 code. lets say your function in form1 is called myButton_Click.
UserControl1.Click += new System.EventHandler(myButton_Click);
Then within UserControl1, create an on-click event (lets say "Control_Click") that simply invokes the UserControl1.Click eventhandler.
private void Control_Click(object sender, EventArgs e)
{
Click?.Invoke(this, new EventArgs());
}
Finally link each control's click in usercontrol to that Control_Click event within the usercontrol's constructor
picturebox1.Click += new System.EventHandler(Control_Click);
label1.Click += new System.EventHandler(Control_Click);

Access a ListView located in a UserControl from the MainForm in Winforms

I have an app that uses a side menu, and for each button (there are 3) on the left side menu, it changes the pages shown.
I tried doing it with multiple panels, but it's a nightmare to maintain in designer, and it's probably not a very good programming habit, I expect.
So I search and found what seemed to be a great idea: UserControl.
But as usual, it's not that simple (for a badly self-taught guy like me)
The general flow of the program is as follows:
a Btn_uc1_Check button that gathers informations and displays them in a uc1_ListView,
a Btn_uc2_Seek button that gathers informations on the net based on the uc1_ListView , and displays them on uc2_ListView,
a Btn_uc3_compile that compiles the info from uc2_ListView into a file,
a Clear button that clears the ListView depending on the UserControl on screen.
Now to the problem:
How on earth do I gain access to a ListView located in a UserControl to be able to read, clear, and add items from the MainFrom or from another UserControl?
I searched and honestly found nothing corresponding to what I needed?
Quite many questions.
You can gain access to any controls in UC. Just change the property "Modifiers" of the ListView in your UC to "Public".
Set that method to public. Do not use keyword "static". Each control
in your form is an instance of a class, not a static class actually. In the main form, create a button and double click on it in VS designer. A method will automatically generated, something like private void button1_Click. When the button is clicked, all of the code lines in button1_Click will run.
Create a public event handler of your user control, then pass the method in main to the handler.
So the UC class will be similar to this:
public event EventHandler button_UC_Click_handler;
public UserControl1()
{
InitializeComponent();
}
private void button_UC_Click(object sender, EventArgs e)
{
button_UC_Click_handler.Invoke(sender, e);
}
In main form:
public MainForm()
{
InitializeComponent();
userControl11.button_UC_Click_handler += UserControl11_button_UC_Click_handler;
}
private void UserControl11_button_UC_Click_handler(object sender, EventArgs e)
{
MessageBox.Show("You have clicked it!");
}
Good luck!

Capture KeyDown when event does not reach my control

First: I know that there are literally thousands of answers like: "Add a handler to Keyboard.KeyDownEvent and have fun!". But in my situation this does not work.
I have a custom control CustomControl which derives from Canvas but has no Children. Instead it draws its "children" directly to the DrawingContext in the OnRender. My Control is HitTestVisible, it is tab stop but is not focusable. It is often reused and sometimes in a ScrollViewer.
This CustomControl has a custom implementation for selecting something like text, and should copy that selected text to the ClipBoard on Ctrl+C.
To do this, I added a handler in the constructor:
public CustomControl()
{
//// ... other stuff
AddHandler(Keyboard.KeyDownEvent, (KeyEventHandler)CopyMarkedNucleotidesToClipboard);
}
And here is the Problem: When my control is inside a ScrollViewer, and I hit Ctrl+C, the KeyDownEvent is raised on the ScrollViewer and bubbles up to the window, and therefore never reaches my Control.
What can I do inside my CustomControl to capture every Ctrl+C in the window where it resides?
PS: I already set IsTabStop="False" and Focusable="False". But then the next sibling of the ScrollViewer would raise the event which would still bubble up to the window. And I don't want to go through all controls which are higher in the visual tree and set IsTabStop="False" and Focusable="False" which would be wrong...
I already found this article http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx but I think, that there must be a more wpf-like way!
The suggestion of Sinatr was correct! Thanks!
The solution is to find the parent window in the load and subsribe to his KeyDownEvent.
public CustonControl()
{
Loaded += HookToCtrlC;
}
private void HookToCtrlC(object sender, EventArgs e)
{
var parentWindow = Window.GetWindow(this);
parentWindow.KeyDown += CopySelectedTextToClipboard;
}
private void CopyMarkedNucleotidesToClipboard(object sender, KeyEventArgs e)
{
Clipboard.SetText("Hello World!");
}

wpf click button in usercontrol calls event in parent window

This must have been asked before, but I am fairly new and don't quite know how to express myself...
1) I have a UserControl that basically acts as a toolbar. I re-use the toolbar in each window, hence the need for a uc.
2) The toolbar is filled with buttons
3) the usercontrol doesn't act on the button (no code), but it should pass the event back to the parent window so the code in the parent window fires up.
How can I do this? Is this a routed event? any sample code in vb.net would be appreciated!
On you user control, you need events that you can fire when the buttons are clicked. Then in your form, you handle the events just like you do for every other control. IE:
public event Button1_ClickedEventHandler Button1_Clicked;
public delegate void Button1_ClickedEventHandler(object sender);
private void Button1_Click(object sender, EventArgs e)
{
if (Button1_Clicked != null) {
Button1_Clicked(this);
}
}
You can call the event whatever you want and pass whatever you want. Here you will notice I am NOT sending the button but THIS, which in this case should be the User Control.

Throwing events through objects

I'm developing a Windows Mobile 5.0 or above application with .Net Compact Framework 2.0 SP2 and C#.
I have a Winform (Form1) with a control (Control1) that contains another control (Control2). For example, a winform with a panel and inside this panel there is a button, but in my case Control1 and Control2 are custom controls.
Control2 has an event, Click, that is thrown when the user does click over it. This click event must be handled by Form1. To do it, first I handle the event on Control1 that throws a new event that is handled on Form1. This my code:
On Control1:
public event EventHandler Control2Click;
private void control2_Click(object sender, EventArgs e)
{
if (Control2Click != null)
{
Control2Click(sender, e);
}
}
On Form1:
private void control1_Control2Click(object sender, EventArgs e)
{
// Do something interesting.
}
Is there a better way to handle Control2_Click directly in Form1? I don't know if my way has a bad performance and this kind of events can be handled better.
Thank you!
No, you are doing it right. It is the correct way the bubble an event out of a nested control that isn't directly accessible from a container control. You'd normally use the PerformClick() method to fire the Click event but this doesn't appear to be available in CF.
Perf is not an issue, calling a delegate target is very fast, a dozen nanoseconds or so on a desktop machine. Click is a "human-time" event, anything less than 20 milliseconds is perceived as "instant".
What's stopping you from hooking up the Control2 Click event directly from Form1? Does Control1 expose Control2 via a property? Or perhaps expose an event on Control1 which actually hooks up to the Control2 Click event? For example:
// In Control1
// Assuming Control2 is some sort of Save button, for example
public EventHandler SaveClicked
{
add { control2.Click += value; }
remove { control2.Click -= value; }
}
Note that:
If you change the value of control2 within Control1, the event handlers won't be "transferred" which would be be unfortunate
The sender parameter in the event handler will refer to Control2, not Control1
To be honest I wouldn't expect this to be a performance problem however you handle it - it's just a delegate invocation or two.

Categories