简体   繁体   English

C# 为类和运算符分配默认属性 =

[英]C# Assigning default property for class and operator =

Problem 1:问题1:

I have a simple winforms app and I want to DataBind my Person.Name property to a textbox.我有一个简单的 winforms 应用程序,我想将我的 Person.Name 属性数据绑定到一个文本框。 Name is of type StringField.名称的类型为 StringField。 I originally defined the Name property as String.我最初将 Name 属性定义为 String。 The data binding works great on value types such as String.数据绑定对字符串等值类型非常有效。 I would like the StringField.Value property to be the default property of StringField.我希望 StringField.Value 属性成为 StringField 的默认属性。 I want to see the value of StringField.Value in the textBox rather than the text "FieldApp.StringField".我想在文本框中看到 StringField.Value 的值,而不是文本“FieldApp.StringField”。

Problem 2:问题2:

I would like to be able to assign a string to a StringField using operator =.我希望能够使用运算符 = 将字符串分配给 StringField。 This assignment would result in the StringField.Value member being set.此分配将导致设置 StringField.Value 成员。

Can this be accomplished?这能实现吗?

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

You could create an implicit operator overload.您可以创建一个隐式运算符重载。 Then you can create StringField from strings like this:然后你可以从这样的字符串创建StringField

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

Know that this creates a new StringField object.知道这会创建一个新的StringField对象。 I wouldn't necessarily advice you to do this.我不一定建议你这样做。

[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;
    }
}

Re data-binding, for some binding targets ( PropertyGrid , DataGridView , etc), you can do this with a TypeConverter (see below).重新数据绑定,对于某些绑定目标( PropertyGridDataGridView等),您可以使用TypeConverter执行此操作(见下文)。 Unfortunately, this doesn't seem to work with TextBox , so I think your best option is to simply add a shim property (as already suggested):不幸的是,这似乎不适用于TextBox ,所以我认为您最好的选择是简单地添加一个 shim 属性(如已经建议的那样):

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

(and bind to NameString ) (并绑定到NameString

In the past, I have used custom PropertyDescriptor implementations to side-step this, but it isn't worth it just for this.过去,我使用自定义PropertyDescriptor实现来回避这一点,但仅仅为了这个是不值得的。

Anyway, a TypeConverter example (works with PropertyGrid and DataGridView ):无论如何,一个TypeConverter示例(适用于PropertyGridDataGridView ):

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

You can implement assignment by providing a conversion operator.您可以通过提供转换运算符来实现赋值。 Given the nature of your class, you should also override the Object methods:鉴于您的类的性质,您还应该覆盖 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();
  }
}

You can hade the StringField by mapping the Name property to the Name.Value field internally in your class.您可以通过将 Name 属性映射到类内部的 Name.Value 字段来生成 StringField。

so you can define the Name property like this:所以你可以像这样定义 Name 属性:

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

Here _name is your StringField variable.这里 _name 是您的 StringField 变量。

The assignment operator cannot be overridden in C#.在 C# 中不能覆盖赋值运算符。 You could however have a property to do the type conversion for you and expose that one the class但是,您可以拥有一个属性来为您进行类型转换并将该属性公开给类

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM