I want to create a custom wpf control that contains a Button and a ContentPresenter. As WPF controls are supposed to be lookless I created a class that is supposed to contain my control's behaviour and I put default style for the control inside generic.xaml file. So far so good.
But how do I make my button raise an event (routed event?) and handle it in my control's class? I figured out that I can add code behind file for the ResourceDictionary from generic.xaml and put my event handlers there, but that would associate behaviour of my control with its template and is therefore not desirable. Another idea I have seen (but not yet tried) is to use TemplatePart mechanism to locate some key controls inside the template and subscribe to events in code. But that does not seem flexible enough for me because it may happen that the user of my control will want to replace button with a control that does not have any event I know of at the time of designing my control.
So how do I raise event in XAML when button is clicked and subscribe to it in my control's code file?
Override the OnApplyTemplate method of the control.
That is where you know the template has been applied and you can use GetTemplateChild to get a reference to a control.
E.g.:
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var myButton = this.GetTemplateChild("myButton") as Button;
if(myButton != null)
{
myButton.Click += ...;
}
Related
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.
I'm working on c# WinForm.
I have an custom UserControl : MyControl : UserControl, INotifyPropertyChanged. I attached a method on event on event VisibleChanged : this.VisibleChanged += new System.EventHandler(this.MyControl_VisibleChanged);
My application have some pages, each page is a control like MyControl. Top of MainWindows contains Button, used to switch tab.
My problem is that my function MyControl_VisibleChanged is called only when Visible is changing to true. I added a test in a tab to check MyControl.Visible, when I select the other tab, MyControl.Visible is false but no event is raised.
I've try to define a new property Visible for this control but value is never set, only the base value is modify.
Can you help me to find a solution ?
This is a quirk in the way Visible works, explained here. His solution was to use properties that he has complete control over, but you could instead have a method allowing the tab switches to tell their children to raise their VisibleChanged event that extra time.
The first two answers to this question may also be useful.
Is there an event that gets fired when a user control gets added onto a Form?
I need this to get the size of the Parent control of the user control.
But when the user control gets initialized etc, the Parent = null.
Because the user control hasn't been added yet onto the Form. So i can't get the Parent control (which is the Form) at this point.
So i'll have to do the re-sizing of the user control afterwards.
There is a ParentChanged event that all Controls inherit. In the event handler method you can inspect the Parent property, which will be set to the new parent at that point.
You can try using the Control.ParentChanged event. This will fire whenever the parent of the control is changed, so you can check if the parent is the form and then continue with how you want to react.
Alternatively, you can use the Control.ControlAdded event.
You have the ControlAdded event on the form, wich is initialized in your InitializeComponent(). Most of the time this event is duely placed after the adding of components. If you place it before the adding of UserControls to the form you will fire events each time you add a component.
I would recommend adding the usercontrol you need such specific control over in your codebehind and not move the eventhandler.
If you do that you can add a parent to your usercontrol which might give you the information you need.
var textBox = new TextBox {Parent = this};
Why is the 1st button "active" when I am not hovering over the button or anything. This seems to happen after I change tabs.
I suspect that when I change tabs, it focuses the 1st control. Is that the case? I am developing a MVVM app, so from my view model, how might I focus the text box instead?
Since WPFs concept of focus is kinda complicated, I have a class called FocusEnforcer.
It really really makes sure the desired control gets the focus, no matter what.
public static class FocusEnforcer
{
public static void EnforceFocus(UIElement element)
{
if (!element.Focus())
{
element.Dispatcher.BeginInvoke(DispatcherPriority.Input,
new ThreadStart(delegate()
{
element.Focus();
}));
}
}
}
This kind of behavior requires just that: a behavior. Or, at least, a new attached property.
Create an attached property for tab controls.
Create a handler for changes to this attached property.
In this handler, subscribe to the TabControl's SelectionChanged event.
In the SelectionChanged event handler, use the TabControl.FindName method to get the text box.
Execute the FocusManager.SetFocusedElement method using the TabControl as the focus scope.
I have a user control that needs to load a child control when a button is clicked.
The trouble is that it has to request the control from another class.
So in the button click event, I call the function to get me my control, and add it to the page, like this:
UserControl ctrl = ExampleDataProvider.GetControl(some params...);
myDetailPane.Controls.Add(ctrl);
The GetControl method looks like:
public static UserControl GetControl(some params...)
{
ExampleDetailPane ctrl = new ExampleDetailPane();
ctrl.Value = "12";
ctrl.Comment = string.Empty;
return ctrl;
}
This isn't working due to the page's lifecycle - the Page_Load of the child control gets fired and its controls are null.
I kind-of know that my approach is wrong and why, but don't know the best way to go about fixing it! Could anyone help?
Dynamic controls must be re-created on every postback, this Article is a good link about how to persist dynamic controls and their state.
If you want to access your control in PostBack or you want to bind Event, you have to create them in CreateChildControls() method.
private UserControl _uc = null;
/// <summary>
/// Creates all controls.
/// </summary>
/// <remarks>All the controls must be created in this method for the event handler</remarks>
protected override void CreateChildControls()
{
_uc = new UserControl ();
this.Controls.Add(_uc);
base.CreateChildControls();
}
Create your control in Page_Init. Then make it visible on your Button_Click event.
(CTRL+C/CTRL+V from some other question I answered last week):
Everything that has to be maintained between page cycles should be declared in Page_Init, not Page_Load.
All the initialization, like adding event handlers, and adding controls should be added during initialization, as the state is saved between page cycles. Handling with the content of controls and the viewstate, should be done in Load.
Check also http://msdn.microsoft.com/en-us/library/ms178472.aspx.
Init
Raised after all controls have been initialized and any skin
settings have been applied. Use this
event to read or initialize control
properties.
.
Load
The Page calls the OnLoad event method
on the Page, then recursively does the
same for each child control, which
does the same for each of its child
controls until the page and all
controls are loaded.
Use the OnLoad event method to set
properties in controls and establish
database connections.
Two possible approaches:
Have the control in the page but not loaded with anything until they click their button. Then you can populate the values in the control. This has the benefit of being within the page life cycle. Note, you can always use the "display: none" style setting for the that your user control is in. Then, as part of the OnClick for the button, you can reveal the div making your control visible.
You could pop up another window, though obviously this has the potential for being blocked by popup blockers.