How to set focus on a control within a custom control? - c#

I have a custom control containing a textbox and a button. I use the custom control as an editing control for a specific column in an ObjectListView.
On CellEditStarting event I do:
private void datalistViewProducts_CellEditStarting(object sender, CellEditEventArgs e)
{
var ctl = (MyCustomControl)e.Control;
e.Control = ctl;
}
The ObjectListView's ConfigureControl method already calls the control's Select method. It works fine if I have a usercontrol inheriting directly from a standard TextBox.
So I added the following code to my usercontrol:
public new void Select()
{
textBox.Select();
}
However, having a usercontrol as described above, the Select method does not move the focus to the textbox.
What am I missing here?

You can create a method in CustomUserControl, say FocusControl(string controlName)
and then call this method to focus the control in Custom Control.
Create the method in your custom User Control-
public void FocusControl(string controlName)
{
var controls = this.Controls.Find(controlName, true);
if (controls != null && controls.Count() == 1)
{
controls.First().Focus();
}
}
Call this method-
//textBox1 is the name of your focussing control in Custom User Control
userControl11.FocusControl("textBox1");

The only way that made it finally work was to add the following code in the usercontrol:
protected override void OnEnter(EventArgs e)
{
base.OnEnter(e);
textBox.Select();
}

Related

WPF. Button.IsDefault = true. Without UpdateSourceTrigger=PropertyChanged

I have many forms with a lot of textboxes. And I want to add to that forms a button with IsDefault = true. Then fill any property and press enter. If I will not set UpdateSourceTrigger=PropertyChanged on textbox, it will not see my input.
The problem is that I do not want to add UpdateSourceTrigger=PropertyChanged to each textbox, combobox, checkbox, and etc.
Is there any way to trigger everything to write it's data to the source without adding UpdateSourceTrigger=PropertyChanged?
Call the BindingExpression.UpdateSource method in the click event handler for each of the Controls (TextBox, CheckBox, etc.) that you have in your Window/UserControl, like this:
private void ButtonBase_OnClick(object sender, RoutedEventArgs e) {
this.UpdateSourceTrigger(this);
MessageBox.Show($"Field1: {this.vm.Field1}\nField2: {this.vm.Field2}\nField3: {this.vm.Field3}");
}
public void UpdateSourceTrigger(UIElement element) {
if (element == null) return;
var children = LogicalTreeHelper.GetChildren(element);
foreach (var e in children) {
if (e is TextBox txtBox) {
var binding = txtBox.GetBindingExpression(TextBox.TextProperty);
binding?.UpdateSource();
}
if (e is CheckBox chkBox) {
var binding = chkBox.GetBindingExpression(CheckBox.IsCheckedProperty);
binding?.UpdateSource();
}
// add other types, like ComboBox or others...
// ...
this.UpdateSourceTrigger(e as UIElement);
}
}

Show property editor by click on property text box in PropertyGrid

I am creating a touch application on a no-keyboard pc, where I use a PropertyGrid to manage classes to store / save the app configuration.
I need to edit the propertyline's rows with a custom keyboard that I created (not the system's) setting the class as UITypeEditor
Now the custom keyboard is showed when right button is clicked.
Is it possible to show when on the row start edit (like textbox Enter event),
or when the row is selected ?
The editor control which you see in PropertyGrid is a GridViewEdit control which is a child of PropertyGridView which is a child of the PropertyGrid.
You can find the edit control and assign an event handler to its Enter event. In this event, you can find the SelectedGridItem and then call its EditPropertyValue method which is responsible to show the UITypeEditor.
private void propertyGrid1_SelectedObjectsChanged(object sender, EventArgs e)
{
var grid = propertyGrid1.Controls.Cast<Control>()
.Where(x => x.GetType().Name == "PropertyGridView").FirstOrDefault();
var edit = grid.Controls.Cast<Control>()
.Where(x => x.GetType().Name == "GridViewEdit").FirstOrDefault();
edit.Enter -= edit_Enter;
edit.Enter += edit_Enter;
}
private void edit_Enter(object sender, EventArgs e)
{
var item = this.propertyGrid1.SelectedGridItem;
if (item.GetType().Name == "PropertyDescriptorGridEntry")
{
var method = item.GetType().GetMethod("EditPropertyValue",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance);
var grid = propertyGrid1.Controls.Cast<Control>()
.Where(x => x.GetType().Name == "PropertyGridView").FirstOrDefault();
method.Invoke(item, new object[] { grid });
}
}
Note: For modal editors the Enter event is annoying and repeats over and over again. To avoid this you can use Click event of the control.
Also as another option you can rely on SelectedGridItemChanged event of PropertyGrid and check if e.NewSelection.GetType().Name == "PropertyDescriptorGridEntry" then call EditPropertyValue of the selected grid item using reflection.

How to get selection in DropDownList control in parent control Page_Load method?

I am relatively new to asp.net.
I have parent custom user control and child custom user control.
As you can see above child control has DropDownList control.
When selection changed in DropDownList control postback accrued and Page_Load(object sender, EventArgs e) method of the parent control is fired,
at this stage(in Page_Load method of the parent control) I need to get the selected value in DropDownList.
Any idea how can I get the selected value in DropDownList in Page_Load method of the parent control?
One option would be to expose either the control on your child control, or an accessor to the value of the same control. For example, in your code behind for the child control you could have a property like
public TextBox MyTextBoxControl
{
get { return MyLocalTextBoxControl; }
}
And then access it on the Page_Load of the main control like so:
protected void Page_Load(object sender, EventArgs e)
{
...
var textValue = MyChildControl.MyTextBoxControl.Text;
...
}
Of course, you will need to decide if it makes better sense from a reusability standpoint whether to expose just the text portion of the control (or whatever property you need at the parent level) or access to the whole control.
For reference, you would expose access only to the text portion of the sub-sub control as follows.
public string MyTextBoxControlText
{
get { return MyLocalTextBoxControl.Text; }
set { MyLocalTextBoxControl.Text = value; }
}

C# Populating a TreeView with TabControl

So I've been able to populate a TreeView with the tabnames in WPF/XAML binding but haven't done this before with C# Windows Forms.
I want to have the treeview display the project name based on what file is open and then tabcontrol names below it (these are static -- one is called editor and the other fields).
I'll add a context menu later, but the sole purpose would be to make the tabs visible based on their state with click events from the treeview.
My problem is I can't figure out how to associate them in the treeview. I found this code, can anyone tell me if I'm on the right track here?
private void treeView1_AfterSelect(Object sender, TreeViewEventArgs e)
{
// Set the visibility of the tabpages from the treeview
if ((e.Action == TreeViewAction.ByMouse))
{
if (e.Node.Name == "Editor")
{
this.editForm.tabControl1.SelectedTab = editForm.Editor;
}
if (e.Node.Name == "Fields")
{
this.editForm.tabControl1.SelectedTab = editForm.Fields;
}
}
}
You could use the TreeNodes's Tag property to hold the associated Tab Name.
if (e.Action == TreeViewAction.ByMouse)
{
TabPage p = tabControl1.TabPages[e.Node.Tag]
tabControl1.SelectedTab = p;
}

C#: Convert a string to an object reference

Basically a button's tag property is the name of an existing combobox which I need to dynamically reference. It's a generic function to handle multiple buttons. Help
private void SQLButton(object sender, EventArgs e)
{
magic(((Button)sender).Tag.ToString());
}
private void magic(string currentcombo)
{
string CurrentText = (ComboBox).(currentcombo).Text;
}
You can set the Tag property to the actual ComboBox and avoid your problem altogether.
//code when defining your button...
{
sqlButton.Tag = comboBoxA; //instead of comboBoxA.Name
}
private void SQLButton(object sender, EventArgs e)
{
Button button = sender as Button;
ComboBox comboBox = button.Tag as ComboBox;
if (comboBox == null )
{...}
else
{
magic(comboBox);
}
}
private void magic(ComboBox currentcombo)
{
string CurrentText = currentcombo.Text;
}
I think I understand what you're after -
You'll want to change your "magic" routine to something like:
private void magic(string currentCombo) {
ComboBox box = this.Controls.Find(currentCombo) as ComboBox;
if(box != null) {
// You can do your "work" here...
string currentText = box.Text;
}
}
If you have the string id value of a control then you can use FindControl to get a reference to the control.
Something like ...
Button btn = (Button)FindControl("some_id");
I don't know if its winforms or asp.net. I am assuming it to be winforms
You could use this.Controls(theNameofTheControl) instead of magic.
Have a look at the Controls.Find Method, to get the instance of the Control using the name.
If currentcombo paramter in magic function is the identifier for the control you are going to change then use Page's function FindControl:
string CurrentText = ((ComboBox)FindControl(currentcombo)).Text;
Page.FindControl() method searches the page naming container for a server control with the specified identifier.

Categories