2010-03-10 20 views
5

Çalışma zamanı üzerinde DisplayNameAttribute öğesinin nasıl değiştirileceğini merak ediyorum, bazı dönüşümler yaptığımda, özellik kılavuzumda DisplayName metriği yerine Metre yerine Feet olmasını istiyorum. mümkün?Özellik Grid C kullanmak için çalışma zamanındaki DisplayNameAttribute nasıl değiştirilir? #

[DisplayName("Meters")] 
public double Distance 
    { 
    get{return distance;} 
    } 
+0

Bunu her zaman 'Distance' olarak ayarlayabilir ve birimleri değerlere dahil edebilirsiniz. "Mesafe | 34 metre" ve "Mesafe | 112 feet". –

+0

Örneğim örneğin çiftse nasıl yaparım? – DogDog

cevap

11

Bunu yapmanın bir çok yolu vardır. En basit olanı, i18n ürünlerinin belirli bir şekilde nasıl yapıldığına benzer bir şey yapmaktır - niteliği alt sınıfı ve metni durdurma; ancak bu yalnızca siz türüne sahipseniz çalışır ve bir öznitelikten içeriğe erişemezsiniz. Bu vb özelliklerine bileşen modeli görünümüne erişim sağlar ve PropertyGrid ile çalışacaktır Bu ;-p sonraki iki seçenekten daha basittir, ancak DataGridView beri bakmak

sonraki şeyler, TypeConverter olurdu

Listede bir sonraki ICustomTypeDescriptor - uygulanacak eğlenceli bir arabirim değil, ancak kendi özellik tanımlayıcınızda takas edebilirsiniz. Bu, türüne sahip olmanızı gerektirir (arayüz desteğini sağlamak için).

Son olarak, CustomTypeDescriptor son gibidir, ancak sahibi olmayan türleri için bile çalışır ve her iki tip ve nesne düzeyde (her şey sadece nesne destekler) de meta büküverdi erişime izin verir.

Hangisini seçmeliyim? TypeConverter'un en mantıklı olacağını sanıyorum; Nesne bağlamına (alt sınıfsal bir özellik sağlamaz) ihtiyacınız vardır, ancak ekstra karmaşıklığa ihtiyacınız yoktur.

İşte bir örnek; Not: TypeConverter kodunda nesne bağlamına erişimimiz olduğunu unutmayın. Ad basitse, TypeConverter (özelliği oluştururken) içine koymak yeterli olmalıdır. displayname nitelik hala (bu durumda) gibi mevcut ve sadece adını değiştirmek istiyorsanız

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Windows.Forms; 
class MyFunkyTypeConverter : ExpandableObjectConverter 
{ 
    public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) 
    { 
     PropertyDescriptorCollection props = base.GetProperties(context, value, attributes); 
     List<PropertyDescriptor> list = new List<PropertyDescriptor>(props.Count); 
     foreach (PropertyDescriptor prop in props) 
     { 
      switch (prop.Name) 
      { 
       case "Distance": 
        list.Add(new DisplayNamePropertyDescriptor(
         prop, "your magic code here")); 
        break; 
       default: 
        list.Add(prop); 
        break; 
      } 
     } 
     return new PropertyDescriptorCollection(list.ToArray(), true); 
    } 
} 
class DisplayNamePropertyDescriptor : PropertyDescriptor 
{ 
    private readonly string displayName; 
    private readonly PropertyDescriptor parent; 
    public DisplayNamePropertyDescriptor(
     PropertyDescriptor parent, string displayName) : base(parent) 
    { 
     this.displayName = displayName; 
     this.parent = parent; 
    } 
    public override string DisplayName 
    {get { return displayName; } } 

    public override bool ShouldSerializeValue(object component) 
    { return parent.ShouldSerializeValue(component); } 

    public override void SetValue(object component, object value) { 
     parent.SetValue(component, value); 
    } 
    public override object GetValue(object component) 
    { 
     return parent.GetValue(component); 
    } 
    public override void ResetValue(object component) 
    { 
     parent.ResetValue(component); 
    } 
    public override bool CanResetValue(object component) 
    { 
     return parent.CanResetValue(component); 
    } 
    public override bool IsReadOnly 
    { 
     get { return parent.IsReadOnly; } 
    } 
    public override void AddValueChanged(object component, EventHandler handler) 
    { 
     parent.AddValueChanged(component, handler); 
    } 
    public override void RemoveValueChanged(object component, EventHandler handler) 
    { 
     parent.RemoveValueChanged(component, handler); 
    } 
    public override bool SupportsChangeEvents 
    { 
     get { return parent.SupportsChangeEvents; } 
    } 
    public override Type PropertyType 
    { 
     get { return parent.PropertyType; } 
    } 
    public override TypeConverter Converter 
    { 
     get { return parent.Converter; } 
    } 
    public override Type ComponentType 
    { 
     get { return parent.ComponentType; } 
    } 
    public override string Description 
    { 
     get { return parent.Description; } 
    } 
    public override PropertyDescriptorCollection GetChildProperties(object instance, Attribute[] filter) 
    { 
     return parent.GetChildProperties(instance, filter); 
    } 
    public override string Name 
    { 
     get { return parent.Name; } 
    } 

} 

[TypeConverter(typeof(MyFunkyTypeConverter))] 
class MyFunkyType 
{ 
    public double Distance {get;set;} 

    public double AnotherProperty { get; set; } 
} 
static class Program 
{ 
    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.Run(new Form { Controls = { 
      new PropertyGrid { Dock = DockStyle.Fill, 
       SelectedObject = new MyFunkyType { 
        Distance = 123.45 
       }} 
     }}); 
    } 
} 
0

Öznitelikler türün bir parçası olarak derlenmiştir, bu nedenle çalışma zamanında değiştirilemezler.

Tüm değerleri her zaman sakladığınız bir iç ölçü birimini belirlemek için alternatif bir çözüm olabilir. Metre, iyi bir adaydır. Daha sonra, tüketici sınıfınız ile tüm değerleri farklı bir formata dönüştürmekten sorumlu orijinal sınıf arasında yer alan "çevirmen" hizmetleri oluşturun.

+0

Reflection ile bunu yapamaz mı? – Nick

+0

Yapabileceğiniz en iyi şey, istediğiniz özellik ile yeni bir derleme oluşturmak olacaktır. Ama herhangi bir kullanım olup olmadığını bilmiyorum. –

+0

@Nick yansıması "salt okunur" - ör. bunları yürütmek için gerekli bilgiler dahil olmak üzere, türler hakkında bilgi verebilir, ancak bunları değiştiremezsiniz. @Nader'ın belirttiği gibi, istediğiniz değişikliklerle yeni bir montaj oluşturabilirsiniz, ancak bu muhtemelen herhangi bir problemi çözmez. –

0

Üniteyi görünen adda ayarlamak biraz garip, ancak gerçekten yapmak istediğin şey buysa, tek çözümün mülklerini özel PropertyDescriptors ile yayımlamak (bir TypeConverter veya özel bir Tip sayesinde) Tanımlayıcı) ve DisplayName özelliğini geçersiz kılmak.

burada da Yanıtlanmış: Change DisplayName attribute for a property

0

bu işe yarayacak mı bilmiyorum, ama DisplayName bir Özellik olduğunu. Her sınıf ve her sınıfın üyeleri atanmış özniteliklere sahip olabilir. Bununla birlikte, PropertyInfo'nun size bu Niteliklere erişim sağlayacağını söyler. Şimdi, bu yöne giderseniz ve PropertyInfo.GetCustomAttributes() ya da onun gibi bir şeyle karşılaşırsanız ve Attribute değerinizi alırsanız, bu sizin sadece Nick'e söylediğiniz gibi salt okunur olduğunu mu söylüyorsunuz?

0

, bu özelliğin PropertyDescriptor kullanabilirsiniz. Sadece niteliği buluncaya ve değeri değiştirene kadar özellik özelliklerine bakın.

İlgili konular