How to force validation of UserControl? - c#

Validations for my textbox controls work normally/as expected. However, for my created UserControl, also containing a textbox (which also contains other controls as well), it's not always validated, except when the user manually selects/focuses another control, which will of course fire the Validating event.
Now, I've found from searches about Form.ValidateChildren() (which works btw), but this method validates all children as described in the documentation, which is not the ideal solution to a form with many controls, as opposed to only validating the single control in question.
Additional info:
I use ErrorProvider to show errors - I need to consider the position
of the icon in the case of my UserControl (which again, contains
multiple controls inside).
Validating and Validated events are performed on my UserControl, not the TextBox inside it. Both events are on the form where the usercontrol is used.
The Text property of the TextBox inside my UserControl is modified
internally (inside my UserControl class)
`
//some code inside usercontrol
private void SomeMethod()
{
...
textBox.Text = ...;
ParentForm.ValidateChildren(); // works but does this on all controls which is not the ideal operation, which is to perform validation only on this usercontrol
}
`
With the above-mentioned info, when I modify the Text property manually, the Validating event is, as expected on the design, not raised since UserControl.TextBox != UserControl. It's not an option for me to perform validation on the UserControl.TextBox instead of the UserControl.
With all that explained, how should I manually/forcefully trigger the validation only for the UserControl, when UserControl.TextBox.Text is modified, without resorting to Form.ValidateChildren which targets all of the form controls? Or is it not possible?

Related

How to know when all Controls' Handles on a Windows Form have been created? [duplicate]

In Windows Forms when a UserControl or Form first time becomes visible the Load event is fired.
http://msdn.microsoft.com/en-us/library/system.windows.forms.usercontrol.load.aspx
Is there any such event for controls like Checkbox, TextBox, Label ?
No. You could use the HandleCreated event, it is fired when the native window for the control is created. The first event you can rely on to run after the class constructor ran. It is triggered when the parent adds the control to its Controls collection and the control becomes visible.
Beware however that it this event can fire more than once. Controls may be re-created when certain properties get reassigned, the kind that requires the native CreateWindowEx() function to be called with new style flags. So you'll at least need to carry around a bool flag that keeps track of this.
Also note that setting properties of a control after the native window is created is pretty inefficient. All Winforms controls were designed to allow properties to be set before the native window is created. Whatever code you are generating almost surely should use the class constructor instead. Either of the derived control itself. Or in the code of the parent, much like InitializeComponent() does for a form or user-control.
The same is true for the existing Load event. It tends to be over-used due to the VB6 legacy where the Load event was very important. In Winforms however it is only required for code that depends on the final location and size of a control or form. Which may be different from the design properties due to form scaling. Any other code belongs in the constructor.

Raising event from custom control added dynamically to the form

I have a custom control that can be added multiple times to a form. There can be multiples occurrences of this custom control on the same form. These controls are added and removed by the user. The user can right click on some control inside the custom control to reveal a menu.
When selecting an item from this menu, an event should be raised on the form. I made a custom event and realized that it could't be usable if the control was added dynamically, because the form doesn't know it. I can't add an event handler referring to a control that doesn't exist. Is there some other way to raise an event on the form from custom control that doesn't require the form to know it? By the way, my custom controls are added to a FlowLayoutPanel.
Thanks for the help!
You just wire up the event handler in the code when you add the control e.g.
MyButton.Click += ButonClickEventHandler;
Page.Controls.Add(MyButton)
Agree with Ben - otherwise, there are messy ways of doing it (depending on how your control is set up). For example INotifyPropertChanged Inerface or through Windows API messaging (and listener) - but unless you have a very strange set up, then as Ben said, simply add a handler when you add the control. You can always use a generic callback method and use custom event args to identify which has triggered it.

Controlling event-driven navigation in a WPF application

I think the title for this question is probably wrong, but I'm not sure quite how to phrase it. I have a C# 4.0 (VS2010) WPF application.
This application consists of a single window with a header including the basics (logos, captions, etc) and a set of navigation buttons (back, retry, next, etc). The rest of the window is comprised of a listbox that is populated with one or more usercontrols based on what mode the app is currently in.
The way the code is currently written when the mode changes the listbox is cleared, all new user controls are added, and the buttons are set to their required state. This is fine for the initial state of each window mode but I'm having trouble deciding a good approach to update the navigation buttons as the contents of the controls change.
For example one screen is a configuration screen and there are three user controls contained within the listbox. These controls are custom classes that inherit from UserControl. Additionally they implement an interface that defines a method 'bool Validate' which determines if the control has been completely filled out.
This same scenario could apply to lots of other situations but this is a generic use case that is pretty straightforward to understand. When the screen initially loads the 'Next' button, whose visibility is controled by the parent window, is visible but disabled as the child controls can't possibly yet be valid. At some point as the user fills out arbitrary data within one or more controls each one would return true if its Validate method was called.
At the point where all controls are valid, the next button would then become enabled. Fairly straightforward design.
The problem is each control doesn't know what screen it is on, and this is by design. I don't want the controls having to be aware of each other and updating a button status in the parent window. I also don't want the parent window to run a polling thread to call Validate every second because in some cases the validation could be complex.
I'm thinking that the change event of each control within the UserControl (text boxes, radio buttons, etc) would all call a trigger a private validate event and this would set some public property on the interface or class.
f I can do that is there a way for the parent window to respond in an event-driven manner to the change of that property? I'm not looking to do this in WPF, doing this in C# code is preferable as I don't want to get into the complexity of WPF quite yet. I'm just not sure, other than constant polling, how to tell when every control's 'IsValid' property will have synchronized all to 'true', if that is even a good approach.
EDIT:
Okay, here is another way to ask the question. I have a List of something (in this case a list of an interface) and want to be able to respond to a public property change on each item in the list so I can take an action when all items are (bool in this case) true. The above explains the use case, but this is a more generic version of the question.
EDIT:
#Vincent "you might do it in an even simpler way with a custom "ValidatedChanged()" event that you can hook in the same way."
It turns out that this is really what I was looking for. The property notification approach seems to be more for ease of use with data-bound controls. I read a lot of posts on this site about how to implement that but it really wasn't what I wanted. I just wanted my objects to notify that an event occured, which happened to be a property change, but that is beside the point. I found documentation on implementing an event in an interface and I have it working now. Thanks for pointing me in the right direction and helping me realize what is really is that I needed.
So you have a ListBox which contains all your controls, and when all controls are validated, the Next button should be enabled ?
If so, when one of your control validates, you might search all sons of the ListBox to check them for validation, using VisualTreeHelper.GetChildren to get them all.
If you don't want / can't have a handle on the ListView, you might find it by searching up the visual tree starting from the control that just validated.
Each 'Validated' event of each control would be handled by a 'CheckIfAllValidated' event handler, and when all are validated, you could raise a 'AllValidated' events that would be handled by the button (and maybe some other controls as well) to enable it.
Edit : I understood that you did not want each component to know about their children, but notice that even the quite common PropertyChanged event has a 'sender' fields that tells who did raise the event. So any listener of a PropertyChanged on, say, the 'validated' property, can go up the visual tree, stop when it encounters a ListView, then search downstairs if all control that have a validated property do have this property set to true...
Edit 2 :
To be more clear about how to do it, either in your window new or on the window loaded event
or maybe on the ContentRendered Event, depending on how your controls are loaded, you
might use once that code to hook a handler to all your controls :
For Each ThisControl In MainListView.
Dim ThisControlType = ThisControl.GetType
Dim ThisControlPropertyChangedEvent = ThisControlType.GetEvent("PropertyChanged")
' you might wanna check here if event is not null / nothing
ThisControlPropertyChangedEvent.AddEventHandler(ThisControl, New PropertyChangedEventHandler(AddressOf APropChanged))
Next
and you write the APropChanged somehow like that :
Public Sub APropChanged(ByVal sender As Object, ByVal e As PropertyChangedEventArgs)
If e.PropertyName = "Validated" Then
Dim ValidatedForAll = True
For Each ThisControl In MainListView.Items
Dim ThisControlType = ThisControl.GetType
Dim ThisControlValidatedProperty = ThisControlType.GetProperty("Validated")
'you might wanna check for non null here
If Not ThisControlValidatedProperty.GetValue(ThisControl, Nothing) Then
ValidatedForAll = False
Exit For
End If
Next
If ValidatedForAll Then
MessageBox.Show("Yeeppee") ' you might send an event instead.
End If
End If
End Sub
Edit 3 : you might do it in an even simpler way with a custom "ValidatedChanged()" event that you can hook in the same way.

How do I add events to nested server controls? (ASP.Net)

I am building a custom master page type control i.e. sort of like a datagrid but should be easier to add custom functionality into it. It's going great but part of the desired functionality is to have a paging control that switches on and off and part of that control would be a textbox that displays the current page number and on TextChanged redirects to the new page of the dataset.
The problem I'm having is that technically the textbox which has its event fired is embedded in a control that is embedded in the control you actually put on the page sort of like
Page
|
Display Control
|
Paging Control
|
Textbox
Buried all the way down there the event is not firing. Worse the postback javascript isn't even being written onto the page (Nothing on the page posts back so far this is the only bit that really needs to).
I've been trawling around Google for quite a while now and picked up that I need to implement INamingContainer (done) and I need to add the control into the page's control tree (is Pre_Init too late for that? When's a good time to Add the Control to the page?) then the event should fire, apparently. But I've been unable to find an example of best practice on this there are quite a few near misses where people are having button angst but this isn't a button.
So can anyone point me in the direction of getting a control embedded in a control embedded in a control added to a page to behave properly?
You need INamingContainer only if you plan to add more than one instance of your custom control to the same page. What it does is enabling unique id generation so you don't end up with controls with the same ID. I recommend you inherit from CompositeControl when creating your custom control.
Pre_Init is not too late. Actually it is pretty early considering the lifecycle. You can instantiate custom controls and add them to the live controls collection in a lot of places. I would recommend you do it in Page_Init (before viewstate is loaded) or Page_Load(after view state is loaded). Even if you add it later in the page lifecycle the control will catch up in events.
To subscribe to events of child controls you can use the FindControl method:
MyControl myControl = Page.FindControl("MyControl1");
TextBox textBox = myControl.FindControl("TextBox1") as TextBox;
The answer was a combination of the above answer and the comment on the original question. The vital thing to get the event to happen is to make sure that your controls (parent and child) inherit from CompositeControl and INamingContainer e.g.
public partial myControl:CompositeControl,INamingContainer
etc...
Then you override your composite control's CreateChildControls() method and create your controls and do the wire up there. This will ensure correct bubbling. and mean that the event handling takes place within your comoposite control...

WinForms designer: Add control and make it visible for the designer

I have a WinForms user control Host with a custom UI Editor.
Through that editor, a child control (Child) can be added to Host.
(The UI Editor creates Child and sets Child.Parent = Host)
Child is handled through a Holder<Child> helper class, which is set as Tag property of e.g. a ListViewItem.
The respective code - some of it, at least - gets added to the form: Holder is created, and set as Tag, which is enough to be created at runtime, too.
However, Child is not visible to the designer - it is displayed, but it can't be selected, nor does it occur in the drop down list with controls for the parent form.
I would like to:
see the Child control in the designer, so that I can modify properties
get notified if the control is removed
Is this possible?
[edit] Thanks all for your input. I've decided to skip the designer - I hoped to throw together something quickly, but apparently it requires more planning than I should allow myself to spend on it right now.
Usethis.Controls.Add(/*Instance of the child*/); on the host class. Then for the notification add event handler for the host's ControlRemoved event (this.ControlRemoved += new ControlEventHandler(Host_ControlRemoved);).
I can't say I fully understand exactly what you are trying to do.
If you are dealing with the problem of how a "child" Control of a UserControl placed on a Form at Design-Time can be made to function as a container onto which you can drag-and-drop other controls from the Toolbox : this CodeProject article by Henry Minute may be helpful : Designing Nested Controls. For example : you have a UserControl with a Panel inside it : an instance of the UserControl is placed on a Form : in the Design-time view of the Form : you want to be able to drag-drop controls onto the Panel in the UserControl and have them become child controls of the Panel : Henry's article will show you how to do that.
This from Microsoft : How to make a UserControl object acts as a control container design-time by using Visual C#
Perhaps might also be useful, although it seems like you already have this step accomplished.

Categories