2009-01-11 7 views
6

Problème 1:C# Affectation propriété par défaut pour la classe et l'opérateur =

J'ai une application simple WinForms et je veux Databind ma propriété Person.Name à une zone de texte. Le nom est de type StringField. J'ai initialement défini la propriété Name en tant que String. La liaison de données fonctionne très bien sur les types de valeur tels que String. Je voudrais que la propriété StringField.Value soit la propriété par défaut de StringField. Je veux voir la valeur de StringField.Value dans le textBox plutôt que le texte "FieldApp.StringField".

Problème 2:

Je voudrais être en mesure d'attribuer une chaîne à un Stringfield utilisant l'opérateur =. Cette affectation entraînerait la définition du membre StringField.Value.

Est-ce que cela peut être accompli?

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"); 
     } 
    } 
} 

Répondre

10

Vous pouvez créer une surcharge de l'opérateur implisit. Ensuite, vous pouvez créer Stringfield à partir des chaînes comme ceci:

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

Sachez que cela crée un nouvel objet StringField. Je ne vous conseillerais pas de le faire.

[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

Vous pouvez hader StringField en mappant la propriété Name au champ Name.Value en interne dans votre classe.

de sorte que vous pouvez définir la propriété Name comme ceci:

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

Ici _name est votre variable Stringfield.

0

L'opérateur d'affectation ne peut pas être remplacé en C#. Vous pouvez cependant avoir une propriété pour effectuer la conversion de type pour vous et exposer que l'on la classe

2

Re-liaison de données, pour certains objectifs contraignants (PropertyGrid, DataGridView, etc.), vous pouvez le faire avec un TypeConverter (voir ci-dessous). Malheureusement, cela ne semble pas fonctionner avec TextBox, donc je pense que la meilleure option est d'ajouter simplement une propriété de shim (comme cela a déjà suggéré):

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

(et se lient à NameString)

Dans le passé, j'ai utilisé des implémentations personnalisées PropertyDescriptor à côté de cette étape, mais il ne vaut pas juste pour cela.

Quoi qu'il en soit, un TypeConverter exemple (fonctionne avec PropertyGrid et 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

Vous pouvez implémenter une affectation en fournissant un opérateur de conversion. Étant donné la nature de votre classe, vous devez également remplacer les méthodes Object:

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(); 
    } 
} 
Questions connexes