I probably have a very simple problem, but could not find a solution. I have a problem with the property binding to a ToolStripLabel. A Label is bound to COM port value in App.Config.
If I bind the property for a System.Windows.Forms.Label label, the update of Text-Property by changing the COM Port works fine as it is supposed to. But when the label is IN ToolStrip (System.Windows.Forms.ToolStripLabel), the label is not updated by changing the value for COM Port at runtime.
It will be changed only by new start of Application.
In the picture there is a current settings of PropertyBinding to ApplicationSettings.
I've already tried:
Application.DoEvents()
toolStrip.Update()
toolStrip.Refresh()
toolStrip.Invalidate()
Nothing makes difference.
Does anyone have an idea what the problem could be?
Greetings,
Sasha
ApplicationSettings
Label Properties Settings
Example
The ToolStripLabel Component doesn't implement DataBindings, as the Label Control does (that's why you can see a Label Control update its Text when the current setting is changed). When you add PropertyBindings to the Text property through the Designer, the Text is just set to the Properties.Default setting selected (you can see that in the Designer.cs file).
You can build your own ToolStripLabel that implements IBindableComponent, decorate it with ToolStripItemDesignerAvailability flags that allow the ToolStrip or StatusStrip to acknowledge the existence of this custom Component, so you can add it directly from the selection tool.
Add a PropertyBinding to the Text property and now, when the Setting changes, the Text is updated. You can see in the Designer.cs file that a DataBinding has been added.
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.Design;
[ToolStripItemDesignerAvailability(
ToolStripItemDesignerAvailability.ToolStrip |
ToolStripItemDesignerAvailability.StatusStrip),
ToolboxItem(false)
]
public class ToolStripDataLabel : ToolStripLabel, IBindableComponent
{
private BindingContext m_Context;
private ControlBindingsCollection m_Bindings;
public ToolStripDataLabel() { }
public ToolStripDataLabel(string text) : base(text) { }
public ToolStripDataLabel(Image image) : base(image) { }
public ToolStripDataLabel(string text, Image image) : base(text, image) { }
// Add other constructors, if needed
[Browsable(false)]
public BindingContext BindingContext {
get {
if (m_Context == null) m_Context = new BindingContext();
return m_Context;
}
set => m_Context = value;
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ControlBindingsCollection DataBindings {
get {
if (m_Bindings == null) m_Bindings = new ControlBindingsCollection(this);
return m_Bindings;
}
}
}
Related
Problem
I was trying to create a custom control which contains nothing but a label. However, I wanted the label's text to be changed to what the name property of the custom control has received at design time.
This is what my custom control's class looks like:
public partial class Tile : UserControl
{
public Tile()
{
InitializeComponent();
}
[Browsable(true)]
public override string Text { get => label1.Text; set => label1.Text = value; }
}
As you can see, I've overridden the UserControl's Text property in a way that it updates the Label's text too as soon as the Name is updated which in the end did not work. What happened was when I dragged the control from Toolbox to form the label got updated as expected but the moment I build the project, the designer got refreshed and the Label's text was lost.
What I tried
DesignerSerializationAttribute
Going through Google I came upon a solution given at StackOverflow
itself by Hans Passant that using
DesignerSerializationAttribute(DesignerSerializationVisibility.Visible)
can solve the problem as the value the Text property is given will
be persisted in the initialization code which seems valid when it was
getting lost at first (value didn't persisted and lost upon designer
repaint).
So I changed my property like this:
[Browsable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public override string Text { get => label1.Text; set => label1.Text = value; }
Doing such change actually solved the issue and now it was working even If I build the project.
What I found
Though my issue got solved but then I started to look for another way
to approach the same result.
While experimenting more with my code I found that If I create
another property that exposes the label's Text property and update
it using the overridden Text property it works exactly what it
was working using DesignerSerializationAttribute.
Here what the new code looks like:
[Browsable(false)]
public string LabelText { get => label1.Text; set => label1.Text = value; }
[Browsable(true)]
public override string Text { get => LabelText; set => LabelText = value; }
I wanted to know that
Why this works (even without DesignerSerializationVisibility):
Text---->LabelText---->Label's Text
I might be asking something very obvious right now but I've been reading about it since hours which made it a bit confusing for me .
If you look at the source code of UserControl, you can see the Text property is marked as not serializable by designer, so basically the value of the property will be lost after you close the form:
[Browsable(false),
EditorBrowsable(EditorBrowsableState.Never),
Bindable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public override string Text {
get {
return base.Text;
}
set {
base.Text = value;
}
}
But in your alternative solution, designer will serialize LabelText property, and later will use its value to return as Text. That's why it works.
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.
I have found this article from http://www.codeproject.com/Articles/687430/Selecting-Forms-Controls-at-Design-Time
This is written in VB.NET, so I converted into C# version.
And I created a class called "DataGridViewBandColumn" inherits from DataGridViewColumn like below.
public class DataGridViewBandColumn : DataGridViewColumn
{
private Collection<DataGridViewTextBoxColumn> _TargetControls = new Collection<DataGridViewTextBoxColumn>();
[EditorAttribute(typeof(BANANA.Windows.Controls.Design.UITypeEditorDropDownCollection), typeof(System.Drawing.Design.UITypeEditor))]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Collection<DataGridViewTextBoxColumn> ATargetControls
{
get { return _TargetControls; }
set { _TargetControls = value; }
}
}
I can see the property and select other columns from form design time like below.
But as soon as I click OK button on property window, it loses the items that I selected and it is not saved on the Form1.Designers.cs file.
Where do I have to check to fix this?
Anyone has any idea?
I have a small question regarding databinding and user controls.
I construct (using C# 2010) a user control which is basically a wrapper for a ComboBox, and it has a custom property, which when changed, sets the value of the ComboBox. Conversely, should the selected item in the ComboBox change, the value of the property is changed.
Now, I could do this by trapping the "selected value changed" event on the ComboBox, and setting the property, and I could, in the property setter, set the selected value of the ComboBox, but I surmised I might also be able do this with DataBinding.
And it nearly works, but not quite.
It works at run-time, but not at design time and I was wondering if this could be easilly resolved.
For example, if at design time, I select the instance of my user control, and from the properties window select my control's custom property, and change it, the ComboBox does not reflect the change.
Any pointers to something I have missed would be greatfully received. Obviously, I could set the ComboBox selected value, but it would be nice if DataBinding would do it for me.
Thanks
(Here is my user control. Drop one on a form and use the IDE to change the "Position" property)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
namespace WindowsFormsApplication13
{
public partial class UserControl1 : UserControl, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public enum enumPosition : byte
{
Unknown, First, Second, Third
}
public UserControl1()
{
InitializeComponent();
var bindingList = new BindingList<KeyValuePair<enumPosition, String>>();
foreach (enumPosition value in Enum.GetValues(typeof(enumPosition)))
{
bindingList.Add(new KeyValuePair<enumPosition, String>(value, value.ToString()));
}
this.comboBox1.DisplayMember = "Value";
this.comboBox1.ValueMember = "Key";
this.comboBox1.DataSource = bindingList;
this.comboBox1.DataBindings.Add("SelectedValue", this, "Position", false, DataSourceUpdateMode.OnPropertyChanged);
}
private enumPosition _position = enumPosition.Unknown;
[DefaultValue(typeof(enumPosition), "Unknown")]
public enumPosition Position
{
get { return _position; }
set
{
if (value != _position)
{
_position = value;
this.OnPropertyChanged(new PropertyChangedEventArgs("Position"));
}
}
}
private void OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, e);
}
}
}
Works for me too !
Environment - VS .Net 2008
Only difference I think might be 'Re-Building' the application instead of just 'Build' ?
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;
}
}