I have wrote a winform control with vs2005.
This control is inherited from UserControl. At first, it worked well. But after some time, error occured when load winform designer.
The error message is below:
"NameCaption" isn't the property of type "System.Windows.Forms.UserControl".
Here is the define of NameCaption:
public string NameCaption
{
get
{
return this._nameCondCaption;
}
set
{
this._nameCondCaption = value;
this.nameLabel.Text = value;
}
}
private string _nameCondCaption = "Name";
I think NameCaption is not the root cause.
How can I fix the problem?
Thanks in advanced.
I have changed the code like this:
public string NameCaption
{
get
{
return this.nameLabel.Text;
}
set
{
this.nameLabel.Text = value;
}
}
private string _nameCondCaption = "Name";
Now it works. But I still don't understand why.
You could try making it hidden to the designer serialization using the DesignerSerializationVisibility attribute like this:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public string NameCaption
{
get
{
return this._nameCondCaption;
}
set
{
this._nameCondCaption = value;
this.nameLabel.Text = value;
}
}
private string _nameCondCaption = "Name";
Related
I am not very experienced with Windows Forms and am not pretty sure how I should tackle with this task the best way possible. I have a class which looks like this:
public class VariableMapping
{
private string variableName;
private string variableText;
private string variableSelector;
public VariableMapping(string variableName, string variableText, string variableSelector)
{
this.VariableName = variableName;
this.VariableText = variableText;
this.VariableSelector = variableSelector;
}
public string VariableName
{
get { return this.variableName; }
set { this.variableName = value; }
}
public string VariableText
{
get { return this.variableText; }
set { this.variableText = value; }
}
public string VariableSelector
{
get { return this.variableSelector; }
set { this.variableSelector = value; }
}
}
I want to create a DataGridView which should be bound to a number of elements of type VariableMapping in a list. However, I want only 1 of the properties(VariableText) of every instance to be shown in the DataGridView but I want to be able to address the whole object through the DataGrid when I need to. I also need to add 2 more custom columns: a ComboBox with predefined values and a NumberBox.
It might seem a really simple task but I'm trully unexperienced in WinForms and couldn't find a solution I can use already. Thank you!
Edit: I am trying something like this but it doesn't seem to work properly:
public partial class MappingTable : Form
{
private DataGridView dataGridView1 = new DataGridView();
public MappingTable(List<VariableMapping> variableMappings)
{
InitializeComponent();
var colors = new List<string>() { "#color_k1", "#color_k2", "#color_s1" };
dataGridView1.AutoGenerateColumns = false;
dataGridView1.AutoSize = true;
dataGridView1.DataSource = variableMappings;
DataGridViewColumn titleColumn = new DataGridViewColumn();
titleColumn.DataPropertyName = "VariableText";
titleColumn.HeaderText = "Variable";
titleColumn.Name = "Variable*";
dataGridView1.Columns.Add(titleColumn);
DataGridViewComboBoxColumn colorsColumn = new DataGridViewComboBoxColumn();
colorsColumn.DataSource = colors;
colorsColumn.HeaderText = "Color";
dataGridView1.Columns.Add(colorsColumn);
DataGridViewTextBoxColumn opacityColumn = new DataGridViewTextBoxColumn();
opacityColumn.HeaderText = "Opacity";
dataGridView1.Columns.Add(opacityColumn);
this.Controls.Add(dataGridView1);
this.AutoSize = true;
}
}
Given a very basic WinForms custom/user control, using System.Windows.Automation it is possible to manipulate built in properties for the custom control.
This is done like this:
public object GetPropertyValue(int propertyId)
{
if (propertyId == AutomationElementIdentifiers.NameProperty.Id)
{
return "Hello World!";
}
}
What I would like to do is expose custom properties to ui automation such as ReadyState, LastAccessed, Etc.
Is this possible?
No, you can't extend the list of properties, and this is complicated by the fact you use Winforms that has a poor UI Automation support (it uses IAccessible with bridges etc.).
What you can do though is add some fake objects to the automation tree, for example, here is a sample Winforms UserControl that does it:
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
Button button = new Button();
button.Location = new Point(32, 28);
button.Size = new Size(75, 23);
button.Text = "MyButton";
Controls.Add(button);
Label label = new Label();
label.Location = new Point(49, 80);
label.Size = new Size(35, 13);
label.Text = "MyLabel";
Controls.Add(label);
MyCustomProp = "MyCustomValue";
}
public string MyCustomProp { get; set; }
protected override AccessibleObject CreateAccessibilityInstance()
{
return new UserControl1AccessibleObject(this);
}
protected class UserControl1AccessibleObject : ControlAccessibleObject
{
public UserControl1AccessibleObject(UserControl1 ownerControl)
: base(ownerControl)
{
}
public new UserControl1 Owner
{
get
{
return (UserControl1)base.Owner;
}
}
public override int GetChildCount()
{
return 1;
}
public override AccessibleObject GetChild(int index)
{
if (index == 0)
return new ValueAccessibleObject("MyCustomProp", Owner.MyCustomProp);
return base.GetChild(index);
}
}
}
public class ValueAccessibleObject : AccessibleObject
{
private string _name;
private string _value;
public ValueAccessibleObject(string name, string value)
{
_name = name;
_value = value;
}
public override AccessibleRole Role
{
get
{
return AccessibleRole.Text; // activate Value pattern
}
}
// note you need to override with member values, base value cannot always store something
public override string Value { get { return _value; } set { _value = value; } }
public override string Name { get { return _name; } }
}
And this is how it appears in the automation tree (using the inspect.exe tool):
Note this technique also supports writing back to the property because it's based on the ValuePattern.
I have a PropertyGrid control to which I bind a container with an array of complex objects:
// Collection
public class ParametersCollection
{
private ParameterObject [] _parameters = null;
[Category("SubReportParams")]
public ParameterObject [] Parameters
{
get { return _parameters; }
set { _parameters = value; }
}
public ParametersCollection()
{
// _parameters initialization here...
}
}
// Complex object
public class ParameterObject
{
private string _name = "";
private string _value = "";
[Category("Information"), DisplayName("Name")]
public string Name
{
get { return _name; }
set { _name = value; }
}
[Category("Information"), DisplayName("Value")]
public string Value
{
get { return _value; }
set { _value = value; }
}
}
Everything works fine, except two cases:
In example, if array _parameters has only 2 items, default array size is 4 and items with indexes 2 and 3 are nulls. PropertyGrid displays these items as empty fields. How to force PropertyGrid to ignore these fields and simply not displaying it?
_parameters variable is an array type, so _parameters items are displayed with their indexes from 0 to n. Is there a posibillity to display them with their names from property ParamObject.Name instead of their indexes from an array?
For the fist question, the easiest way is to add a "fake" property computed from the "real" property. It's not perfect, but you can use various attribute to help:
DisplayName to give the fake property the name of the real property
Browsable(false) instructs the property grid to skip the real property
EditorBrowsable(never) instructs Visual Studio's intellisense to not show this property in external code.
[Browsable(false)]
public ParameterObject[] Parameters
{
get { return _parameters; }
set { _parameters = value; }
}
[Category("SubReportParams"), DisplayName("Parameters")]
[EditorBrowsable(EditorBrowsableState.Never)]
public ParameterObject[] NonEmptyParameters
{
get
{
return _parameters.Where(p => p != null).ToArray();
}
}
For the second question, one simple way is to add a ToString() implementation like this:
public class ParameterObject
{
public override string ToString()
{
return Name;
}
}
Otherwise, you can to add a custom TypeConverter to the class.
How can I write a C# winforms code like this?
CheckedListBox items don't have 'Tag' and 'ValueMember' properties.
I know there are many alternatives to this. But I need to work it this way.
private void LoadPermissionsToCheckedListBox()
{
Role selectedRole = (Role)comboBox1.SelectedItem;
int i = 0;
foreach (Permission p in selectedRole.PermissionItems)
{
checkedListBox1.Items.Add(p);
checkedListBox1.Items[i].Tag = p;
}
checkedListBox1.DisplayMember = "PermissionKey";
checkedListBox1.ValueMember = "PermissionID";
}
There is no Tag property, but the CheckedListBox accepts any object (you don't have to put just strings in it). You can create your custom class to hold your data:
public class CheckListBoxItem
{
public Permission Tag;
public string Text;
public override string ToString() { return Text; }
}
and then add this object as item
foreach (Permission p in selectedRole.PermissionItems)
{
checkedListBox1.Items.Add(new CheckListBoxItem()
{
Tag = p,
Text = p.PermissionKey
});
}
Check:
http://social.msdn.microsoft.com/Forums/en-us/csharpgeneral/thread/80f29165-acb3-421f-b5bb-856ba99da703
I am looking for a datepicker like what microsoft provides, but it doesn't support null values, and since this is tied to a nullable field on a database that isn't acceptable.
I found this one, but according to the comments at the bottom of the page it has issues with binding to a database. I also have one in my project that I inherited, but it has similar issues (sometimes it shows values, sometimes it doesn't). Does anyone know of one that works?
Use a date picker to populate a textbox and if they want the field to be null, just erase the contents of the textbox (and then handle the blank input accordingly).
This also provides the added benefit of allowing the user to type in their date if they so choose.
Smart FieldPackEditor has a datepicker that is nullable. I believe it does everything that you need. I wish this was around when I was dealing with this sort of stuff. I still remember all the workarounds I had to implement with Microsoft's datepicker control. Uggh!
http://www.visualhint.com/index.php/fieldpackeditor/
why not use a client side datepicker to populate a text field. If the textfield is empty, then you have a null date, otherwise convert the value.
jQuery has a nice easy to use datepicker. http://jqueryui.com
This one seems to work, one of my co-workers had it:
using System;
using System.Windows.Forms;
namespace CustomControls
{
public class NullableBindableDateTimePicker : System.Windows.Forms.DateTimePicker
{
private Boolean isNull = false;
private DateTimePickerFormat baseFormat = DateTimePickerFormat.Short;
private Boolean ignoreBindOnFormat = false;
public NullableBindableDateTimePicker()
{
this.Format = baseFormat;
if (baseFormat == DateTimePickerFormat.Custom) this.CustomFormat = " ";
}
public Boolean IsNull
{
get { return isNull; }
set
{
isNull = value;
this.Checked = value;
}
}
//TODO: Add BaseCustomFormat
public DateTimePickerFormat BaseFormat
{
get { return baseFormat; }
set { baseFormat = value; }
}
public object BindMe
{
get
{
if (IsNull) return System.DBNull.Value;
else return base.Value;
}
set
{
//String s = this.Name;
if (ignoreBindOnFormat) return;
if (System.Convert.IsDBNull(value))
{
// for some reason setting base.format in this.format calls set BindMe.
// we need to ignore the following call
ignoreBindOnFormat = true;
this.Format = DateTimePickerFormat.Custom;
ignoreBindOnFormat = false;
this.CustomFormat = " ";
IsNull = true;
}
else
{
ignoreBindOnFormat = true;
this.Format = baseFormat;
ignoreBindOnFormat = false;
if (baseFormat == DateTimePickerFormat.Custom) this.CustomFormat = " ";
IsNull = false;
base.Value = (DateTime)value;
}
}
}
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (e.KeyCode == Keys.Delete)
{
this.BindMe = DBNull.Value;
}
}
protected override void OnCloseUp(EventArgs eventargs)
{
base.OnCloseUp(eventargs);
BindMe = base.Value;
}
}
}