I want to create a custom control by extending an existing control. In fact, I want to add some features to the original control. How can I another control (a control such as TextBox) to my custom control in its constructor or anywhere else?
public partial class AdvancedKnob : KnobControl
{
private DoubleInput Field_ValueControl = null;
public AdvancedKnob()
{
this.InitializeComponent();
this.Field_ValueControl = new DoubleInput();
this.Container.Add(this.Field_ValueControl); //DOES NOT WORK!!
}
}
Try this:
this.Controls.Add(this.Field_ValueControl);
For more information, go to: How to programmatically add controls to Windows forms at run time by using Visual C#
use
this.Controls.Add(control);
Related
I have written a property in a user control class using set get like this :
public partial class MyUserControl : UserControl
{
public string ServerName { get; set; }
public PagingUserControl()
{
InitializeComponent();
}
}
then by adding this user control to a windows form project I set ServerName in the "Misc" section of properties window.
now here is the question, how can I access ServerName from another usercontrol ? I think I should access the property "ServerName" of the object made by the constructor of "MyUserControl"
The right approach is to reverse the data flow by extracting your model being the value of the ServerName property out of the user control and bind both user controls to it, see Windows Forms Data Binding for details. This way you can save a lot of time on plumbing and passing data between your components.
If you are specifically looking for how to implement this with your existing code then following steps below may be able to help you too. Once you drop an instance of the user control to the form, the designer is going to generate some code for it in the Form1.Designer.cs file.
// the declaration of your user control
private MyUserControl1 myUserControl11;
private void InitializeComponent()
{
// the initialization of your user control
this.myUserControl11 = new WindowsFormsApp3.MyUserControl1();
}
This code makes it possible to access the instance of the user control from the form. If you are asking how to share the value of this property with another control you would need to implement INotifyPropertyChanged inside your user control.
public partial class MyUserControl1 : UserControl, INotifyPropertyChanged
And then subscribe your parent form to this event.
private void InitializeComponent()
{
// subscribe to the user control event
this.myUserControl11.PropertyChanged +=
new System.ComponentModel.PropertyChangedEventHandler(
this.myUserControl11_PropertyChanged);
}
// handle the event by updating the other control
private void myUserControl11_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
textBox1.Text = myUserControl11.ServerName;
}
Once you have notification implemented you may consider looking at how data binding can be used to achieve the data propagation between controls with less code. Hope it helps!
hi all and sorry for the confusing title... can't find the right words yet.
just out of curiosity, I am playing with c# user control, I created a control that is built from a panel, a textbox that is being used as a filter, and some labels / buttons/ etc... that are being filtered.
when ever you change the text of the textbox, all the controls on the panel are visible / invisible depending if their Text property contains the Text of the textbox. very simple.
but I want this user control to be such that the user that uses it can drop more labels or controls to it and they will behave the same, I can't figure out how to do that..
when I am editing the control (adding controls to it), it works as expected and the new controls behave as the old ones without code modifications, but only when I am editing the user control and not when using it.
when I am dragging the user control to a form, I can not add controls to it... when I try to add a label to the control - it is just added to the form and not to the control and therefore the text box is not influencing the added label. what should I do if I want to be able to add the control to a form and then add some controls to the control?
I will be happy for some pointers.
here is the relevant code:
private void textBox1_TextChanged(object sender, EventArgs e)
{
foreach (Control c in panel1.Controls)
{
if (c.Text.Contains(textBox1.Text))
{
c.Visible = true;
}
else
{
c.Visible = false;
}
}
}
edit - pictures added.
as you can see - i typed 1 in the filter text box and all the controls except button1 are now invisible - and of course the bad behaving label.
Thanks,
Jim.
This problem can be solved easily by following the guidelines in
https://support.microsoft.com/en-us/kb/813450 which decribes step by step How to make a UserControl object acts as a control container design-time by using Visual C#
In order to modify the user control as a design time control container
add the following code to the Declarations section:
using System.ComponentModel.Design;
Apply the System.ComponentModel.DesignerAttribute attribute to the control as follows:
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
public class UserControl1 : System.Windows.Forms.UserControl
{
...
}
Then build the solution.
the control will appear as usual in the Toolbox and can be added to forms. Additional controls such as buttone , text boxes etc.. can be added to the control as required.
You describe one of the reasons why I almost never use UserControls. Anything that isn't done to the original UC must be done in code..
You can instead make it a class that is not a UserControl, ie make it a simple subclass of Panel (or FlowLayoutPanel as I do here merely for convenience, while dropping stuff on it during my tests).
class FilterPanel : FlowLayoutPanel
{
TextBox tb_filterBox { get; set; }
Label st_filterLabel { get; set; }
public FilterPanel()
{
st_filterLabel = new Label();
st_filterLabel.Text = "Filter:";
this.Controls.Add(st_filterLabel);
tb_filterBox = new TextBox();
this.Controls.Add(tb_filterBox);
// st_filterLabel.Location = new Point(10, 10); // not needed for a FLP
// tb_filterBox.Location = new Point(100, 10); // use it for a Panel!
tb_filterBox.TextChanged += tb_filterBox_TextChanged;
}
void tb_filterBox_TextChanged(object sender, EventArgs e)
{
foreach(Control ctl in this.Controls)
{
if (ctl != tb_filterBox && ctl != st_filterLabel)
ctl.Visible = ctl.Text.Contains(tb_filterBox.Text);
}
}
}
Now after placing it on a form (or whatever) you (or whoever) can drop Controls onto it in the designer and they'll be part of its Controls collection, just like you want it and will behave as expected..
Two notes on subclassing Controls:
If you break one during developement, the Form(s) using it will be broken, too, until you fix the problem. So take a little extra care!
For the Designer to display the Control it always needs to have one parameterless constructor, like the one above. Even if you prefer to have the ability to hand in parameters, one parameterless constructor must still be there or the designer will get into trouble!
I want to create a control in winforms with same behavior as the container controls.
I mean: in design mode, when I drop controls in it, it will group then, just like a groupbox.
This control I'm creating contains some other controls AND a GroupBox.
All I need is: when a control is droped in design mode over my custom control, I'll just put it inside the nested GroupBox.
But I can't figure out how make my control respond to that kind of action in design mode.
Maybe this is what you need, I found it at CodeProject a time ago:
Designing Nested Controls:
This article demonstrates how to allow a Control, which is a child of
another Control to accept having controls dropped onto it at design
time. It is not a large article, there is not much by way of code, and
this may not be either the 'official' or best way to do this. It does,
however, work, and is stable as far as I have been able to test it.
You need to add a Designer attribute to your control, and use a type that derives from or is the ParentControlDesigner Class (needs a reference to the System.Design.dll assembly), like this:
[Designer(typeof(MyCustomControlDesigner1))]
public partial class CustomControl1 : Control
{
public CustomControl1()
{
MyBox = new GroupBox();
InitializeComponent();
MyBox.Text = "hello world";
Controls.Add(MyBox);
}
public GroupBox MyBox { get; private set; }
}
public class MyCustomControlDesigner1 : ParentControlDesigner
{
// When a control is parented, tell the parent is the GroupBox, not the control itself
protected override Control GetParentForComponent(IComponent component)
{
CustomControl1 cc = (CustomControl1)Control;
return cc.MyBox;
}
}
hi
on a windows form (not WPF) I dynamically create buttons on a flowlayout and I would like to add some properties to them simply to store other values (int and string) with the buttons for latter use.
Button bn = new Button();
bn.Text = "mybutton";
bn.Name = "mybutton";
toolTip1.SetToolTip(bn, "some tip");
bn.Location = new Point(200, 200);
bn.Size = new Size(110, 30);
bn.BackColor = SystemColors.Control;
bn.Show();
flowLayoutPanel1.Controls.Add(bn);
I have about 6 values I would like to store with each button as it is different for each button..
Can this be done?
For non-strongly-typed information, you can possibly use the Tag property. Otherwise, I think you'd have to subclass.
Derive from Button:
public class MyButton : Button
{
public string ExtraProperty {get;set;}
}
Personally, I think this is bad code. Really bad code.
Yes. You can assign data like this to the Button.Tag property (inherited from Control). This property is typed as an object so you can assign anything you want to it.
Alternative, you could inherit from Button.
Like all WinForms controls, Button also has a Tag property, which can be used to store arbitrary objects.
public struct MyButtonData {
public int myInt;
public string myString;
}
...
bn.Tag = new MyButtonData() {myInt = 3, myString = "Hello World"};
...
var data = (MyButtonData)bn.Tag;
You can either:
Create a control, derived from Button, and add the additional properties.
Create a class to encapsulate the data you want to assign to the each button, instantiate the class, and then point the control's "Tag" property at the instantiated object.
The Tag property was designed for this very purpose.
Something you would like to do in this case would be to create a custom control. With a custom control, you have more freedom than with the standard control. Not only will you inherit all the functionality from the existing control you are building your custom control on. You will also have the opportunity to add more functionality and properties to your custom control.
Source: Microsoft - Devloper Network.
https://msdn.microsoft.com/en-us/library/ff723977(v=expression.40).aspx
I want to create my own component which consists two other panels. One of them has fixed contents (such as control buttons, etc.) and the other is standard panel, where I can add other components in designer (VS2008).
I know that I have to create UserControl, where I can place my two panels. Then I want to insert my component into the form. But I don't know how to create behavior where I can add other components (such as buttons, labels, etc.) only into second panel in my component.
Could anyone help me with creating this component?
Thank you.
Adam.
Here is an example (snippet of working code):
[Designer(typeof(NavigationalUserControl.Designer))]
public partial class NavigationalUserControl : UserControl
{
class Designer : ControlDesigner
{
public override void Initialize(IComponent component)
{
base.Initialize(component);
var nc = component as NavigationalUserControl;
EnableDesignMode(nc.panel2, "ContainerPanel");
EnableDesignMode(nc.bottomPanel, "BottomPanel");
}
}
// rest of normal class
}
I have found the correct solution (I hope). I have added into my UserControl a property which returns the content panel with this specific Attribute:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Panel PanelContent
{
get { return this.panel2; }
}
Thanks for your help leppie