For ASP controls - let us say we are using button, is it possible to derive from BUTTON, a derived control and create new property called, say , ReferenceID (type say integer) and use that property.
I would like to have a unique id for the control other than the ID we are having
Yes, it is possible and the way you are thinking about it will work but keep in mind that you will have to keep track of the values assigned to this property in ViewState. What I mean is this (untested code):
public class CustomButtom : Button
{
public int ReferenceID {
get {
if(ViewState["ReferenceID"]!=null)
return int.Parse(ViewState["ReferenceID"].ToString());
return -1;
}
set {
ViewState["ReferenceID"]=value;
}
}
}
Related
I have a panel with a dropdown; which I use to set a field in my project.
public class projectclass
{
public enum mainpriority
{
basic,
urgent,
critical
};
public mainpriority _priorityfield { get; set;}
}
The project class use an enum for this field, so to populate the dropdown I do this, to populate it:
mydropdown.options.Clear();
foreach (projectclass._priorityfield priority in projectclass._priorityfield.GetValues(typeof(projectclass._priorityfield)))
{
mydropdown.options.Add( new Dropdown.OptionData() {text = priority.ToString()});
}
This allow me to display the field in the dropbox, for each instance of the projectclass.
All is good in this direction, but if I want to do the opposite (change the value in the dropdown, and change the class field accordingly), I can't make it work.
The main issue is that I try to assign to the class, the value as int (which is what I get back from the dropdown.value() method), but VS tell me that it is not possible to set a _priorityfield type with an int type.
Isn't the enum, equivalent to 0,1,2.....n; so you can either use "basic" or 0 as value?
This is what I do to set the class instance value, from the dropdown, using the onValueChanged delegate
private void UpdatePriority(Dropdown priority)
{
int tempvalue = priority.value;
projectclass_instance1._priorityfield = tempvalue;
}
I assumed that I can pass an int, but VS says that is not possible. I could map each value of the dropdown to an entry in the enum, but I am not sure that it is actually the best solution.
Thanks to Ehsan for the solution.
The error is because I need to cast the int value as enum type, so the value will be correctly recognized.
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 a ListView and a GridView that lists users in an application by names. Whenever the user selects an user to edit, I add a new tab to a TabControl, and bind all editable properties to the WPF controls.
However, when the user is editing in the Edit Tab, the information in the List (specifically, the name field) is also being updated.
Currently I'm making a copy of the object to be edited and leaving the original so it doesn't update the ListView, but isn't there a better/easier way to do this?
I've tried setting the Binding Mode=OneWay, didn't work, and also UpdateSourceTrigger=Explicit in the GridView but also didn't work.
Is there any easier way to do this?
Edit: The way I implemented my INotifyPropertyChanged class is part of the issue, since I have this:
public partial class MyTabControl : UserControl
{
public MyTabControl()
{
InitializeComponent();
//Here, DataContext is a List<Users>
//Users being my Model from the Database
//Some of it's properties are bound to a GridView
//User doesn't implement INPC
}
public void OpenTab(object sender, RoutedEventArgs e)
{
User original = (sender as Button).DataContext as User;
// - This will create a new ViewModel below with the User I'm sending
MyTabControl.AddTab(original);
}
}
And my ViewModel of Users is:
public class UserViewModel : INotifyPropertyChanged
{
public User Original { get; private set; }
public string Name { get { return Original.Name; } set { Original.Name = value; OnPropertyChanged("Name"); } }
public UserViewModel(User original)
{
Original = original ?? new User();
}
// - INPC implementation
}
Since my ViewModel is the one reporting the property changes, I didn't expect my original User to report it as well to the GridView.
The Mode=OneWay causes the information flow to go from the bound data entity to the target UI property only, any change to the UI property will not be bound back.
The reason why the UI content is changing is because the underlying property is read/write (i.e. has a getter and a setter) and is notifying any value change (due to the implementation of the INPC interface).
Presuming that it is a list of User objects you've bound to the GridView, you have two simple options to fix this. Which one is best depends on how much scope for change you have:
change the current Name property on the User object, remove the setter for it. Replace the setter with a method to set the property (i.e. SetUserName(string name)) which then sets the private member variable. Or pass the name as an argument to the constructor of the User entity.
create a new property with only a getter which returns the name and set your binding to that; i.e. public string UserName { get { return Name; }}. As there is only a getter there will be no notification of this property, so if the name does change it won't be propagated via this new property.
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.
I often have a situation like this when creating simple data objects. I have a property called Label that should have a default based on the Name of the object. So if no label is set then the Name is used otherwise use the set Label. A simple example in C#
public class FooBat {
public string Name { get; set; }
public string Label {
get {
if (_label == null) return Name;
return _label;
}
set { _label = value; }
}
}
Now the problem is if you want to edit this object you can't just bind to the Label property or you will get the default value and it will look as if there is a value there when there really isn't. So what I end up doing is create another, read-only property that does the defaulting and I use that is all instances except for when the base object is being edited. This leads to many extra properties with weird names like LabelWithDefault. Another alternative I've tried is to make Label handle the defaulting and make a new property called RealLabel that is used for editing the base object. This is just as bad.
I've thought of moving the defaulting code somewhere else but I haven't found a good place for it in any "normal" model that does not replicate the defaulting code many times.
What I have started to do now is initialize the Label field when the Name field is set (and the Label field is not) and then treat the Label field as a normal field. This works but now the code for defaulting is tied to the wrong property. Why should the Name know that the Label field cares about it? So this is also not "right."
Does anyone have any better ways of handling this problem?
I think there is a little confusion about what I'm asking for. Basically I need two different views to the same object for two different uses. In the first is the editing of the object itself where I want unset fields to show as empty (unset). The second is for all other cases (including when the object is the value of a field of another object) where I want to show each field with its dynamically determined default. Just setting the default the first time doesn't no help because if the (in this case) Name field changes then the Label field must also change until the Label field is set.
The answers are getting closer but I still think that they are too targeted to the example I gave. I was trying to give a concrete example for expository purposes but in reality this is more of a best-practices issue. The example I gave was C# and for a string property but I have the same problem with most languages and systems that I use that have frameworks where the data access and data display are handled for you as well as for data types other than strings. Changing the object that is queried from the data source is possible but often tricky and knowing when to make the change (use a sublclass in this case but not in that one) is particularly difficult.
public class FooBat {
public string Name { get; set; }
public string Label {
get {
if (_label == null)
_label = Name;
return _label;
}
set { _label = value; }
}
}
Regarding your update:
You could subclass your object. The base-class would return null if the field has not been set and the sub-class would return your default value. Thus if you need to query if a value has been set, you would cast to the base-class.
Deleted previous answers/updates for brevity.
Update 2:
I would have to say the best way is to track whether the property has been set or not with an IsPropertySet bool. The Getter for the property would check that value to see if it should be returning its own value or the default value. And the setter for the property would set the IsPropertySet according to the set value (true if the value is not null, false if it is). The code that is using the class could then look at the IsPropertySet value to determine if it is receiving a set value or the default when it calls the Property's Getter.
public class FooBat {
public string Name { get; set; }
public bool IsLabelSet { get; set; }
public string Label {
get {
if (IsLabelSet)
return _label;
else
return Name;
}
set {
IsLabelSet = value != null;
_label = value;
}
}
}
I use a Nameable interface a lot (with getName()). Before I start, I'll suggest that you don't want to do this at all. It should be the domain of your display logic, not your domain objects. Usually it's the code consuming the FooBat that is able to make this decision in a better way than the object itself. That aside...
public interface Label{
string getLabel();
boolean isDefault(); //or isValued() or use instanceof expressions
}
public interface Nameable{
string getName();
}
public class FooBat implements Nameable {
public string Name { get; set; }
public Label Label {
get {
if (_label == null) {
_label = new DefaultLabel(this);
}
return _label;
}
set { _label = value; }
}
}
public class DefaultLabel implements Label{
public DefaultCharSequence(Nameable named){
this.named = named;
}
public string getLabel(){
return named.getName();
}
public boolean isDefault(){ return true; }
}
public class StringLabel implements Label {
...
}
It all essentially boils down to returning a better class for your label object.