كيفية تعديل PropertyGrid في وقت التشغيل (إضافة/إزالة الخاصية والأنواع/التعدادات الديناميكية)

StackOverflow https://stackoverflow.com/questions/313822

سؤال

كيف يمكنك تعديل propertygrid في وقت التشغيل بكل الطرق؟أريد أن أكون قادرًا على إضافة وإزالة الخصائص وإضافة "أنواع ديناميكية"، ما أعنيه بذلك هو النوع الذي ينتج عنه قائمة منسدلة تم إنشاؤها في وقت التشغيل في propertygrid باستخدام TypeConverter.

لقد تمكنت بالفعل من القيام بهذين الأمرين (إضافة/إزالة الخصائص وإضافة نوع ديناميكي) ولكن بشكل منفصل وليس في نفس الوقت.

لتنفيذ الدعم لإضافة وإزالة الخصائص في وقت التشغيل الذي استخدمته مقالة مشروع الكود هذه وقمت بتعديل الكود قليلاً لدعم أنواع مختلفة (وليس فقط السلاسل).

private System.Windows.Forms.PropertyGrid propertyGrid1;
private CustomClass myProperties = new CustomClass();

public Form1()
{
    InitializeComponent();

    myProperties.Add(new CustomProperty("Name", "Sven", typeof(string), false, true));
    myProperties.Add(new CustomProperty("MyBool", "True", typeof(bool), false, true));
    myProperties.Add(new CustomProperty("CaptionPosition", "Top", typeof(CaptionPosition), false, true));
    myProperties.Add(new CustomProperty("Custom", "", typeof(StatesList), false, true)); //<-- doesn't work
}

/// <summary>
/// CustomClass (Which is binding to property grid)
/// </summary>
public class CustomClass: CollectionBase,ICustomTypeDescriptor
{
    /// <summary>
    /// Add CustomProperty to Collectionbase List
    /// </summary>
    /// <param name="Value"></param>
    public void Add(CustomProperty Value)
    {
        base.List.Add(Value);
    }

    /// <summary>
    /// Remove item from List
    /// </summary>
    /// <param name="Name"></param>
    public void Remove(string Name)
    {
        foreach(CustomProperty prop in base.List)
        {
            if(prop.Name == Name)
            {
                base.List.Remove(prop);
                return;
            }
        }
    }

إلخ...

public enum CaptionPosition
{
    Top,
    Left
}

يمكن تنزيل الحل الكامل الخاص بي هنا.

إنه يعمل بشكل جيد عندما أقوم بإضافة سلاسل أو منطقيات أو تعدادات، ولكن عندما أحاول إضافة "نوع ديناميكي" مثل StatesList فإنه لا يعمل.هل يعرف أحد السبب ويمكن أن يساعدني في حلها؟

public class StatesList : System.ComponentModel.StringConverter
{
    private string[] _States = { "Alabama", "Alaska", "Arizona", "Arkansas" };

    public override System.ComponentModel.TypeConverter.StandardValuesCollection
    GetStandardValues(ITypeDescriptorContext context)
    {
        return new StandardValuesCollection(_States);
    }

    public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
    {
        return true;
    }

    public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
    {
        return true;
    }
}

تعمل طريقة استخدام TypeConverter بشكل جيد عندما لا تحاول إضافة الخاصية في وقت التشغيل، على سبيل المثال هذا الرمز يعمل دون أي مشكلة، ولكن أريد أن أكون قادرا على القيام بالأمرين معا.

يرجى إلقاء نظرة على مشروعي.شكرًا!

هل كانت مفيدة؟

المحلول

وماذا كنت تفعل، هو إضافة StatesList (أ TypeConverter) كخاصية.
ما يجب عليك فعله، هو إضافة خاصية مع StatesList كما TypeConverter لها.

نصائح أخرى

اه بالطبع!

myProperties.Add(new CustomProperty("Custom", "", typeof(States), false, true));

[TypeConverter(typeof(StatesList))]
public class States
{
}

يعمل مثل السحر، شكرا لك!

لقد قمت بتحديث مشروعي، وآمل أن يكون مفيدًا للآخرين، ويمكن العثور عليه هنا.

وكان هذا السؤال والإجابة ذات فائدة كبيرة بالنسبة لي.ومع ذلك، كنت بحاجة إلى توسيع نطاق الأمور قليلاً من خلال السماح بقيم القائمة المنسدلة التي تم إنشاؤها في وقت التشغيل.اعتقدت أنني سأقوم بنشر بعض نماذج التعليمات البرمجية فيما يتعلق بما هو مطلوب، في حال وجد أي شخص أنها مفيدة.

أولاً، أضفت معلمة خيارات إلى مُنشئ CustomProperty وأضفت خاصية خيارات:

    private List<string> lOptions;

    public CustomProperty(string sName, object value, Type tType, bool bReadOnly, bool bVisible, List<string> lOptions)
    {
        this.lOptions = lOptions;
    }

    public List<string> Options
    {
        get { return lOptions; }
    }

ثانيًا، أضفت خاصية Options إلى فئة CustomPropertyDescriptor:

    public List<string> Options
    {
        get
        {
            return m_Property.Options;
        }
    }

ثالثًا، اضطررت إلى تعديل طريقة GetStandardValues ​​في فئة النوع الديناميكي الخاصة بي (أي.StatesList) للاستفادة من خاصية الخيارات الجديدة في كائن CustomPropertyDescriptor:

    public override StandardValuesCollection
                 GetStandardValues(ITypeDescriptorContext context)
    {
        CustomPropertyDescriptor descriptor = (CustomPropertyDescriptor)context.PropertyDescriptor;
        return new StandardValuesCollection(descriptor.Options);
    }

أخيرًا، كان عليّ تمرير قائمة الخيارات الخاصة بي عند إنشاء كائن CustomProperty جديد:

    List<string> optionsList = new List<string>(new string[] { "test1", "test2", "test3" });        
    CustomProperty myProperty = new CustomProperty(attr.Name, attr.Value, valueType, false, true, optionsList);

بدلاً من القائمة الثابتة التي مررتها في هذا المثال، يمكنك إنشاء قائمة الخيارات لقائمتك المنسدلة بأي طريقة تريدها، مما يتيح لك التحكم الكامل في الخيارات المتاحة.

وفي حالتي TypeConverter لا ينطبق على الطبقة المتحدة

[TypeConverter(typeof(StatesList))] // not work
public class States
{
}

وأضاف لذلك أنا التجاوز في CustomPropertyDescriptor

public override TypeConverter Converter
{
    get {
        if (this.PropertyType.Equals(typeof(States)) ) {
            return new StatesList(); ; 
        }
        return base.Converter;
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top