2009-01-11 8 views
6

Problema 1:C Asignación de propiedad predeterminada para la clase y el operador # =

Tengo una sencilla aplicación WinForms y quiero databind mi propiedad Person.Name a un cuadro de texto. El nombre es del tipo StringField. Originalmente, definí la propiedad Name como String. El enlace de datos funciona muy bien en tipos de valores como String. Me gustaría que la propiedad StringField.Value sea la propiedad predeterminada de StringField. Quiero ver el valor de StringField.Value en el textBox en lugar del texto "FieldApp.StringField".

Problema 2:

Me gustaría ser capaz de asignar una cadena a un Stringfield usando el operador =. Esta asignación daría como resultado el establecimiento del miembro StringField.Value.

¿Se puede lograr esto?

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 

namespace FieldApp 
{ 
    public class StringField 
    { 
     public string Value { get; set; }  
    } 

    public class Person 
    { 

     //private String _Name; 
     //public String Name 
     //{ 
     // get { return _Name; } 
     // set { _Name = value; } 
     //} 

     //public Person(string name) 
     //{ 
     // Name = name; 
     //} 

     private StringField _Name; 
     public StringField Name 
     { 
      get { return _Name; } 
      set { _Name = value; } 
     } 

     public Person(string name) 
     { 
      Name = new StringField(); 
      Name.Value = name; 
     } 
    } 

    public partial class FieldAppForm : Form 
    { 
     Person person = new Person("steve"); 

     public FieldAppForm() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      //our form contains a button1 and textBox1 

      //this compiles 
      person.Name.Value = "steve"; 

      //this does not. Is there anyway to accomplish this? 
      person.Name = "steve"; 

      //steve appears in the textbox 
      textBox1.DataBindings.Add("Text", person, "Name.Value"); 

      //FieldApp.StringField appears in the textbox 
      textBox1.DataBindings.Add("Text", person, "Name"); 
     } 
    } 
} 

Respuesta

10

Se puede crear una sobrecarga del operador implisit. Luego puede crear Stringfield a partir de cadenas como esta:

StringField field = "value of new object"; 
string value=(string)field; 

Sepa que esto crea un nuevo objeto StringField. No necesariamente te aconsejaría que hicieras esto.

[System.Diagnostics.DebuggerDisplay("{Value}")] 
public class StringField 
{ 
    public string Value { get; set; } 
    public static implicit operator StringField(string s) 
    { 
     return new StringField { Value = s }; 
    } 

    public static explicit operator string(StringField f) 
    { 
     return f.Value; 
    } 
    public override string ToString() 
    { 
     return Value; 
    } 
} 
0

Puede usar StringField asignando la propiedad Name al campo Name.Value internamente en su clase.

por lo que puede definir la propiedad Nombre de la siguiente manera:

string Name 
{ 
    get { return _name.Value; } 
    set { _name.Value = value; } 
} 

Aquí _name es la variable de Stringfield.

0

El operador de asignación no se puede anular en C#. No obstante, usted podría tener una propiedad para hacer la conversión de tipos para usted y exponer que uno la clase

2

Re enlace de datos, por algunos objetivos vinculantes (PropertyGrid, DataGridView, etc.), se puede hacer esto con un TypeConverter (vea abajo). Desafortunadamente, esto no parece trabajar con TextBox, así que creo que su mejor opción es simplemente agregar una propiedad cuña (como ya se ha sugerido):

string NameString 
{ 
    get { return Name.Value; } 
    set { Name.Value = value; } // or new blah... 
} 

(y se unen a NameString)

En el pasado, he utilizado implementaciones personalizadas de PropertyDescriptor para dar un paso al costado, pero no vale la pena solo para esto.

De todos modos, un ejemplo TypeConverter (trabaja con PropertyGrid y DataGridView):

[TypeConverter(typeof(StringFieldConverter))] 
public class StringField 
{ 
    public StringField() : this("") { } 
    public StringField(string value) { Value = value; } 
    public string Value { get; private set; } 
} 

class StringFieldConverter : TypeConverter 
{ 
    public override bool CanConvertFrom(
     ITypeDescriptorContext context, Type sourceType) 
    { 
     return sourceType == typeof(string) 
      || base.CanConvertFrom(context, sourceType); 
    } 
    public override object ConvertFrom(
     ITypeDescriptorContext context, 
     System.Globalization.CultureInfo culture, 
     object value) 
    { 
     string s = value as string; 
     if (s != null) return new StringField(s); 
     return base.ConvertFrom(context, culture, value); 
    } 
    public override bool CanConvertTo(
     ITypeDescriptorContext context, Type destinationType) 
    { 
     return destinationType == typeof(string) 
      || base.CanConvertTo(context, destinationType); 
    } 
    public override object ConvertTo(
     ITypeDescriptorContext context, 
     System.Globalization.CultureInfo culture, 
     object value, Type destinationType) 
    { 
     if (destinationType == typeof(string) && value != null 
      && value is StringField) 
     { 
      return ((StringField)value).Value; 
     } 
     return base.ConvertTo(context, culture, value, destinationType); 
    } 
} 
1

Puede implementar la asignación proporcionando un operador de conversión. Dada la naturaleza de su clase, también debe anular los métodos de Objeto:

public class StringField { 
    public string Value { get; set; } 
    public static implicit operator StringField(string value) { 
    StringField sf = new StringField(); 
    sf.Value = value; 
    return sf; 
    } 
    public override string ToString() { 
    return Value; 
    } 
    public override bool Equals(object obj) { 
    if (obj == null || !(obj is StringField)) return false; 
    return 0 == string.Compare(Value, (obj as StringField).Value); 
    } 
    public override int GetHashCode() { 
    return Value.GetHashCode(); 
    } 
} 
Cuestiones relacionadas