Create a custom UserControl using c# - c#

I Created a custom UserControl using Windows Form Control Library.And I want to create a property of UserControlwhich I can add item to it, then I can select item like comboBox.

WinForms allows you to create a rich design-time environment as well as providing for customised editors at runtime for certain properties that you define.
For example, if I plonk a MessageQueue component onto my WinForms form and view the Properties window, I can see a property named Formatter.
Clicking on the Formatter property however displays a drop-down box showing a preset list of values. This is an example of a UI Type Editor.
One way to do this is to define an enum for your supported values (it could be a dynamic list if you wish).
public enum Muppets
{
Kermit,
MissPiggy,
Fozzie
}
...then after defining your own editor derived from UITypeEditor (see MSDN link below)
class MyMuppetEditor : UITypeEditor { ... }
...you attach it to your control's property that you wish to have a drop-down as so:
[Category("Marquee")]
[Browsable(true)]
[EditorAttribute(typeof(MyMuppetEditor),
typeof(System.Drawing.Design.UITypeEditor))]
public Muppets Muppet {get ; set; }
For more detailed information check out the link below.
More
Walkthrough: Implementing a UI Type Editor
Getting the Most Out of the .NET Framework PropertyGrid Control
EDIT: To allow for dynamic list, try making the property a string because that's what the selection will be bound to and during EditValue() when showing your SelectionControl just display a listbox of your dynamic items

You can do this by using the CategoryAttribute class.
Example:
[Description("Description of property here"), Category("Design")]
public bool my_property;
Check out the MSDN page for a more complete reference on how to use it.
EDIT: In the case of wanting to have a bool property, use this example.
private bool my_bool = true; // this is its default value
[PropertyTab("Property Tab Name")]
[Browsable(true)]
[Description("Description of Property"), Category("Data")]
public bool my_property
{
get { return my_bool; }
set { my_bool = value; }
}

I removed my last answer because I misunderstood your point.
An easy solution would require to make a Collection of enum as a property. The Designer property grid will automatically give you the choice among your initialized Collection with a ComboBox. The displayed names will also be the enum's name.
E.g. (something I made for a TextBox that only allows a certain type of value)
The enum :
enum EnumSupportedType
{
Integer = 1,
Double
}
The class where the property is located :
public class NumericTextBox : TextBoxBase, INumericControl
{
private EnumSupportedType _supportedType = EnumSupportedType.Integer;
public EnumSupportedType SupportedType {
get { return _supportedType; }
set { _supportedType = value; }
}
}
Then these items are suggested in a ComboBox (in the Designer property grid) :
Integer
Double
If you can't use enumerations, you can refer to Providing a Custom UI for Your Properties which seems to be a much harder solution to implement but will solve your problem.
I hope it will help you.

Related

Auto-generate the code-behind name of designer collection items

I have a custom control with a public collection marked as DesignerSerializationVisibility.Content.
When I add items to the collection using the designer, it adds them to the designer file and assigns all desired values but it gives each element of the collection a generic name, such as MyClass1, MyClass2, etc. I want the "Name" property of each item to become the code name of the item so that I can then access the item by its name in code.
This is the functionality of how a ContextMenuStrip and ToolStrip works. In those cases, the Name property shows up as (Name) in the property grid.
Is there an attribute or something I can use to gain this functionality? Or do I have to write a whole custom designer dialog? If so, what's an example of the simplest way I could go about achieving this?
You can try inheriting from Component to get that feature.
In this example, I created a class called PanelItem, which will be the class used in my collection by my own Panel class. I added DesignTimeVisible(false) so that it doesn't populate the component tray in the designer.
Also, I added a Name property that is hidden from the designer but can be used in code. It seemed to work in my tests:
[DesignTimeVisible(false)]
public class PanelItem : Component {
[DefaultValue(typeof(string), "")]
public string PanelText { get; set; }
private string name = string.Empty;
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public string Name {
get {
if (base.Site != null) {
name = base.Site.Name;
}
return name;
}
set {
name = value;
}
}
}
Then my custom panel control:
public class MyPanel : Panel {
private List<PanelItem> panelItems = new List<PanelItem>();
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public List<PanelItem> PanelItems {
get { return panelItems; }
}
}
Resulted in:
I believe your custom control itself is going to require a DesignerSerializer, and that merely decorating the collection with the the DesignerSerializationVisibility.Content will not be sufficient.
I used ILSpy to check: ToolStrip has its DesignerSerializer set to an internal ToolStripCodeDomSerializer, which I think is responsible for generating all the code properties involved.
I think implementing this will be a bit of specialized work. Here's the MSDN article to get you started: http://msdn.microsoft.com/en-us/library/ms171834.aspx. You're looking for an implementation of the CodeDomSerializer, I believe: http://msdn.microsoft.com/en-us/library/system.componentmodel.design.serialization.codedomserializer.aspx.

How can I add a combobox in control designer properties for a WinForms custom control?

I'm creating a custom control with a property that can take value from a set of strings like "Man, Woman". So in in control designer properties I want to show a combobox with these 2 choices.
Is there a standard way to do so ? If not what should I implement ?
The simple way to do that is to add an enum to your code that defines the possible choices for your property, then configure your custom control's property to accept a value of that type. The Properties Window will automatically display a combo box for this property with all of the possible values in your enum listed.
So, for example:
public enum Gender
{
Man,
Woman,
}
public class MyCustomControl : UserControl
{
public Gender UserGender { get; set; }
}
As far as I remember, you should create an enum like:
enum Person
{
Man,
Woman
}
and then make your property of type Person. It should appear in properties as a drop down list.

WinForm DataBinding Hide Property in business object C# .NET

My datagrid (DevExpress) automatically will populate a grid based on the public fields of a business object.
What attribute can I place on the field to tell WinForm databinders to ignore it?
[???HideFromDataBindingSources???]
public bool IsSecurity
{
get { return _isSecurity; }
set { _isSecurity = value; }
}
You should decorate your property with Browsable(false)
Or even implement ICustomTypeDescriptor in your class and filter or dynamically add properties in more agile way.

Dropdown binding in WinForms

Imagine these two classes:
class Part
{
public string Name { get; set;}
public int Id { get; set; }
}
class MainClass
{
public Part APart { get; set;}
}
How can I bind MainClass to a combo box on a WinForm, so it displays Part.Name (DisplayMember = "Name";) and the selected item of the combo sets the APart property of the MainClass without the need to handle any events on the dropdown.
As far as I know, setting ValueMember of the ComboBox to "Id" means that it will try to set APart to a number (Id) which is not right.
Hope this is clear enough!
What you're looking for is to have the ValueMember (= ComboBox.SelectedItem) be a reference to the object itself, while DisplayMember is a single property of the item, correct? As far as I know, there's no good way to do this without creating your own ComboBox and doing the binding yourself, due to the way ValueMember and DisplayMember work.
But, here's a couple things you can try (assuming you have a collection of Parts somewhere):
Override the `ToString()` method of `Part` to return the `Name` property. Then set your `ComboBox`'s `ValueMember` to `"APart"` and leave `DisplayMember` null. (Untested, so no guarantees)
You can create a new property in Part to return a reference to itself. Set the 'ValueMember' to the new property and 'DisplayMember' to `"Name"`. It may feel like a bit of a hack, but it should work.
Do funny things with your `APart` getter and setter. You'll lose some strong-typing, but if you make `APart` an object and `MainClass` contains the collection of `Part`s, you can set it by `Id` (`int`) or `Part`. (Obviously you'll want to be setting it by Id when you bind the ComboBox to it.)
Part _APart;
object APart
{
get {return _APart;}
set {
if(value is int)
_APart = MyPartCollection.Where(p=>p.Id==value).Single();
else if(value is Part)
_APart = value;
else
throw new ArgumentException("Invalid type for APart");
}
}
If you set the ValueMember of the combo box to null, the databinding will return the selected item (i.e. the Part instance) instead of speciied member. Set the DisplayMember to 'Name'.
I made a little research and found this article where the author has been able to bind to nested properties by extending the standard binding source component.
I've tried it and it seems to work fine.
create a backing class to hold the "information", and create properties for all the data. Then implement System.ComponentModel.INotifyPropertyChanged on that class, something like:
private String _SelectedPart = String.Empty;
public String SelectedPart
{
get
{
return _SelectedPart;
}
set
{
if (_SelectedPart != value)
{
_SelectedPart = value;
// helper method for handing the INotifyPropertyChanged event
PropertyHasChanged();
}
}
}
Then create an "ObjectDataSource" for that class (Shift-Alt-D in VS2008 will bring that up while looking at a form), then click on your ComboBox and set the following properties:
DataSource, set to the ObjectDataSource "BindingSource" you just created.
DisplayMember, Set to the Name propertity of the List of parts
ValueMember, Set to the ID member of the List of parts
DataBindings.SelectedValue, set to the SelectedPart on the "BindingSource" you just created.
I know the above sounds complex, and it might take a bit to find all the parts I just described (wish I could give a tutorial or screenshot), but really it is VERY fast to do once you get used to it.
This is by the way, considered "data-binding" in .NET and there are a few good tutorials out there that can give your more information.

How to access properties of a usercontrol in C#

I've made a C# usercontrol with one textbox and one richtextbox.
How can I access the properties of the richtextbox from outside the usercontrol.
For example.. if i put it in a form, how can i use the Text propertie of the richtextbox???
thanks
Cleanest way is to expose the desired properties as properties of your usercontrol, e.g:
class MyUserControl
{
// expose the Text of the richtext control (read-only)
public string TextOfRichTextBox
{
get { return richTextBox.Text; }
}
// expose the Checked Property of a checkbox (read/write)
public bool CheckBoxProperty
{
get { return checkBox.Checked; }
set { checkBox.Checked = value; }
}
//...
}
In this way you can control which properties you want to expose and whether they should be read/write or read-only. (of course you should use better names for the properties, depending on their meaning).
Another advantage of this approach is that it hides the internal implementation of your user control. Should you ever want to exchange your richtext control with a different one, you won't break the callers/users of your control.
Change the access modifier ("Modifiers") of the RichTextBox in the property grid to Public.
Add a property to the usercontrol like this
public string TextBoxText
{
get
{
return textBox1.Text;
}
set
{
textBox1.Text = value;
}
}
I recently had some issues doing this with a custom class:
A user control had a public property which was of a custom class type. The designer by default tries to assign some value to it, so in the designer code, the line userControlThing.CustomClassProperty = null was being automatically added.
The intent was to be able to provide the user control with a custom class at any point while running the program (to change values visible to the user). Because the set {} portion did not check for null values, various errors were cropping up.
The solution was to change the property to a private one, and use two public methods to set and get the value. The designer will try to auto-assign properties, but leaves methods alone.
You need to make a public property for the richtextbox, or expose some other property that does the job of setting the richtextbox text like:
private RichTextBox rtb;
public string RichTextBoxText
{
get
{
return rtb.Text;
}
set
{
rtb.Text = value;
}
}

Categories