I have a custom control that I have created with a bunch standard windows asp controls on it.
Question:
Is it possible to inherit the properties of the parent control into the custom control without re-inventing the wheel?
So for example I have a control with a Button, a TextBox, and a Label.
Normally I can access the properties of that control via Lable1.Text however when these controls are places within a custom control how do I access them without encapsulating all the properties of that control individually.
I was hoping for something like CustomControl1.Lable1.Text or is this not possible
If I use this
public Label lbMovieName
{
get { return this.lbMoveName; }
set { lbMovieName = value; }
}
I get what I need but can you please tell me why I should not do it?
The easiest way is to expose the control through a public read-only property:
public Label MyLabel
{
get { return this.Label1; }
}
However encapsulating just the values you want to expose is definitely a cleaner solution for several reasons:
you can abstract away that actual control type versus being tied to a Label in this case - if you expose the control it will be difficult to swap out the Label with MyNewCoolLabel, for example
You may be exposing more that you want to - the client could change the display properties of the label, etc.
If you are trying to avoid creating properties you can make the controls public (this is not sound OO development). As others have already mentioned you'd be much better served exposing the information that you'd want to share via properties.
The best way and the best practice, I think, is to create properties of your custom control that expose only and exactly what you need. Everything else inside your control should remain private. Something like this:
public string LabelText {
get { return this.Label1.Text; }
set { this.Label1.Text = value; }
}
... and so on for the rest of the properties you need exposed. This will give you nice intellsense response in the designer as well.
Related
I am building some applications that use OPC to control some industrial automation. I have decided it might be a good idea to create some custom controls for standard things I will use such as buttons and text boxes. One of my main reasons was that I felt in an ideal pattern the end object i.e. the button is the one who holds information about the OPC item it refers to otherwise in a typical application my Form class gets polluted by tons of variables that are in my mind scoped more global then they should. I started then by using the Tag property of the button but this requires some overhead code that is the same for each instance. I felt like the right thing to do is subclass controls that I would like to use and provide properties to configure each one.
With that context in mind my real question is this. To make it as portable as possible I decided there should a property to define the OPC Group. I declared a property like this
public class OPCButton : Button
{
[Category("OPC")]
public OPCConnectedGroup
{
get { return _OPCGroup; }
set { _OPCGroup = value; }
}
}
This shows up int the property list when I add the control but I am unable to bind this property even though my Form1 contains
public OPCConnectedGroup Connection1 = new OPCConnectedGroup();
I have resolved that the way to solve this is to probably create an additional control like OPCGrp that can be added to a Form then the Controls can reference this. To test I added a property of type Button and sure enough when I added it and browsed to the property it gave me options for all the buttons on the Form. I have no huge problems with this approach I just want to make sure that Im following a prototypical pattern because I will be responsible for maintaining the control library but not always implementing and Im trying to get it down to a 1-2 step process to implement a control.
Thanks
Matt
When defining OPCConnectedGroup you can inherit Component class.
This way if you have a property of type OPCConnectedGroup in your OPCButton, then at design time, you can put instances of OPCConnectedGroup on the form, and then if you choose your OPCButton at designer, that property of type OPCConnectedGroup will show as a drop down list that you can select one of instances that you put on the form for it.
Example:
If I have such MyButton and MyClass:
public class MyButton : Button
{
public MyClass MyClassInstance { get; set; }
}
public class MyClass : Component
{
public string SomeProperty {get;set;}
}
Then you can put some (or one) instance of MyClass on the component tray of the form:
And then if you select MyButton on your form, you can choose one of MyClass instances from in property grid:
I've been wondering when should I use a Property or a Dependency Property in a custom control for a while, so I thought it'd be a good idea to ask.
Let's say I have a simple (I mean, really simple) UserControl with just a Button and a TextBlock inside it. Let's call the TextBlock "myTextBlock".
Now, if I knew I'll need to bind the Text of that TextBlock to something else, I'd go with a Dependency Property, and that's not a problem.
But what if I just need to set the Text property of the TextBlock to a certain value via XAML and leave it be?
Does it matter if I use a Property instead of a DependencyProperty?
Is one option faster/better than the other one, and if so, why?
Here is a sample with the two options:
public String ButtonText
{
get { return (String)GetValue(ButtonTextProperty); }
set { SetValue(ButtonTextProperty, value); }
}
public static readonly DependencyProperty ButtonTextProperty =
DependencyProperty.Register("ButtonText", typeof(String), typeof(MyUserControl),
new PropertyMetadata(String.Empty, OnButtonTextPropertyChanged));
private static void OnButtonTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(MyUserControl)d.myTextBlock.Text = (String)e.NewValue;
}
And with just the Property:
public String ButtonText
{
get { return myTextBlock.Text; }
set { myTextBlock.Text = value; }
}
I usually go with the simple Property, but I don't know if that's the better approach to use here. Of course it works fine, that's not a problem.
Thanks in advance!
Sergio
I always ask these basic questions
Do I need this to be bindable, animations, or styles and have default
settings that a simple property can't offer for this control?
Do I need to preserve the XAML (expression) with this new property when I am going to serialize/deserialize this
control?
If yes, then I would use DependencyProperty. If not then I'd just use simple properties to be used within this control. It's similar to the question on whether you want to use fields vs properties in an object. My tip is use it when you need the framework's capabilities in your property as they give you more options. You want to know if you need those options or not.
Another reason you want to use DependencyProperty is because you have a base/child control relationship and you want other developers to be able to consume. Instead of you creating interfaces to expose to your control, you provide instant static getter/setter to read/modify the value of your control. You are already creating your interfaces when you create DependencyProperty.
When in doubt, always create simple properties/fields against your control.
I don't agree with the comment that always go with DependencyProperty because it's not cheap compared to a simple property.
For example, you want to make changes to the property and it was a DependencyProperty then chances are, I would need to manually edit the name of the property which is a string and is error-prone. Now compare that to a simple property that gives me a compile time check and I can find the references easily and make some changes to it.
I've had experiences where DependencyProperty was an overkill and should have just used simple properties and the intent would be clear for other developers to read.
I have a combobox embedded in a toolstrip - a ToolStripCombobox instance.
The list of items is the list of values of an enum.
I'd like to be able to load/save the selection (One of the Selected[Index|Item|Text|...] properties, from/to the app's Settings "mechanism".
Ideally, I'd like to be able to do that from the designer.
Normally, hooking a control's property to a certain setting is done (in the designer) from the control's properties, under (ApplicationSettings) - but none of the SelectedXXX properties shows up in there.
FWIW, in the particular case of toostrip-bound combo-boxes, the actual SelectedXXX properties are actually found a bit deeper, at toolStripComboInstance.ComboBox.SelectedXXX.
What I have done so far is configure the binding in code:
m_runTypeCombo //the toolstrip control
.ComboBox //the actual combobox
.DataBindings.Add(
new System.Windows.Forms.Binding(
"SelectedItem",
global::JavaPad.Properties.Settings.Default,
"RunType",
true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged
)
);
The above works, but I was hoping for something cleaner (i.e. designer-based). If the built-in ToolStripCombobox doesn't support this, is there a (simple) way to derive my own type from that, and expose the SelectedXXX properties in such a way that it works with the Application Settings infrastructure (and its support in the designer)?
If you are willing to wrap the TooltipComboBox in your own custom control, you can do it like this:
public class MyCombo : ToolStripComboBox
{
[SettingsBindable(true)]
public int SelectedIndex
{
get { return ComboBox.SelectedIndex; }
set { ComboBox.SelectedIndex = value; }
}
}
Note that I haven't tested this beyond confirming that I can add the control to the ToolStrip, and that I can select a property - You may need to add PropertyChanged Events to make it work fully.
I created this User Control:
I added that User Control to the main Form and now I want to customize it.
So I will have to add text to those 3 Buttons, text in Label, populate ListBox and setting Click Events for the buttons.
What is the proper way to do that?
I looked around on the web and apparently the way to do it is to add public properties in user control that would expose individual property of control that I need.
Something like:
public string Button1Text
{
get
{
return btn1.Text;
}
set
{
btn1.Text = value;
}
}
If I go this route, I would have to add quite a few public properties to this simple user control.
But isnt it easier just to expose whole control in user control like this?
public Button MyButton1
{
get { return this.btn1; }
set { this.btn1 = value; }
}
That way the Main Form can simply access control and its properties as they are needed.
First method is better from the perspective of encapsulation. Second method causes users (forms) of your control to depend on the view of your control, and this prevents changes to the view in the future.
The first bit of code is the correct way to do it. You will have to create a lot of them but it is the proper way to do it.
The first one is much better where you only create properties for each individual property of the button you wish to be able to access from the Parent control.
If you use the second way, then anyone who wishes to use your control will be able to move and resize individual controls inside your control. Then it really isn't a custom control anymore, but more of a panel that is harder to use than a panel. I can't think of any reason why to be able to allow the Parent to move around individual elements in a subcontrol.
I have a c# winform that is a template for all the forms in my project.
My problem is how do I setup some properties for the controls that will be added in the inherited forms from the baseform.
For example I want all the textboxes that will be in the forms to have a specific color, or call an extension method.
Right now I tried the simple idea that popped out:
foreach (Control c in Controls)
{
if(c is ComboBox)
{
//do something
}
if(c is TextBox)
{
//do something
}
}
I put this code in the base form load event, but with no luck. I tried changing the modifiers from the inherited form to protected, but with no luck.
Is there any solution to this problem? Or I am obliged to put this code in all of my forms that inherit baseForm?
Custom Controls are the solution to the problem you have at hand. Simply extend existing Controls to have attributes of your desire and then you could these controls in all of your Forms.
You're beginning to think along the right lines, but you're not quite there yet. The solution to this problem is definitely object-oriented inheritance, but you must be careful not to violate other important principles of OOP, namely encapsulation.
To put things a different way, the form should not be required to "know" about the properties of the controls that it contains. It shouldn't know or care that it contains a ComboBox or a TextBox or a ListView.
Instead, you should subclass each of the child controls that you want to modify, and set their default properties there. Then, you would just add an instance of your custom subclassed control to your form, rather than the built-in control.
So, for example, your custom TextBox class might look like this:
public class CustomTextBox : TextBox // inherit from TextBox
{
public CustomTextBox()
{
// default constructor
}
// other logic...
}