2010-01-12 18 views
5

मैं System.Windows.Forms.PropertyGrid का उपयोग करने की कोशिश कर रहा हूं।क्यों ब्राउज़ करने योग्य विशेषता संपत्ति को बाध्य करने योग्य नहीं बनाती है?

इस ग्रिड में कोई संपत्ति दिखाई देने के लिए BrowsableAttributefalse पर सेट करना चाहिए। लेकिन इस विशेषता को जोड़ना संपत्ति को बाध्यकारी नहीं बनाता है।

उदाहरण: बनाएँ नई Windows Forms परियोजना, और Form1 पर एक TextBox और PropertyGrid छोड़ देते हैं। नीचे दिए गए कोड का उपयोग करना, TextBox की चौड़ाई Data.Width करने के लिए बाध्य नहीं प्राप्त करता है:

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 

     Data data = new Data(); 
     data.Text = "qwe"; 
     data.Width = 500; 

     BindingSource bindingSource = new BindingSource(); 
     bindingSource.Add(data); 

     textBox1.DataBindings.Add("Text", bindingSource, "Text", true, 
      DataSourceUpdateMode.OnPropertyChanged); 
     textBox1.DataBindings.Add("Width", bindingSource, "Width", true, 
      DataSourceUpdateMode.OnPropertyChanged); 

     propertyGrid1.SelectedObject = data; 
    } 
} 

डेटा वर्ग के लिए कोड है:

public class Data : IBindableComponent 
{ 
    public event EventHandler TextChanged; 
    private string _Text; 
    [Browsable(true)] 
    public string Text 
    { 
     get 
     { 
      return _Text; 
     } 
     set 
     { 
      _Text = value; 
      if (TextChanged != null) 
       TextChanged(this, EventArgs.Empty); 
     } 
    } 

    public event EventHandler WidthChanged; 
    private int _Width; 
    [Browsable(false)] 
    public int Width 
    { 
     get 
     { 
      return _Width; 
     } 
     set 
     { 
      _Width = value; 
      if (WidthChanged != null) 
       WidthChanged(this, EventArgs.Empty); 
     } 
    } 

    #region IBindableComponent Members 

    private BindingContext _BindingContext; 
    public BindingContext BindingContext 
    { 
     get 
     { 
      if (_BindingContext == null) 
       _BindingContext = new BindingContext(); 

      return _BindingContext; 
     } 
     set 
     { 
      _BindingContext = value; 
     } 
    } 

    private ControlBindingsCollection _DataBindings; 
    public ControlBindingsCollection DataBindings 
    { 
     get 
     { 
      if (_DataBindings == null) 
       _DataBindings = new ControlBindingsCollection(this); 

      return _DataBindings;  
     } 
    } 

    #endregion 

    #region IComponent Members 

    public event EventHandler Disposed; 

    public System.ComponentModel.ISite Site 
    { 
     get 
     { 
      return null; 
     } 
     set 
     { 

     } 
    } 

    #endregion 

    #region IDisposable Members 

    public void Dispose() 
    { 
     throw new NotImplementedException(); 
    } 

    #endregion 
} 

आप हर संपत्ति पर सच करने के लिए ब्राउज़ करने योग्य विशेषता स्विच करते हैं डेटा में यह काम करता है। अब ऐसा लगता है कि ब्राउज़िंग विशेषता द्वारा बाध्यकारी स्रोत खोज डेटा स्रोत।

उत्तर

6

अपडेट किया गया जवाब अद्यतन उदाहरण के आधार पर:

मैं परावर्तक में कुछ खुदाई किया और पता चला कि "समस्या" ListBindingHelper में वास्तव में है, जो, CurrencyManager द्वारा प्रयोग किया जाता है जो बदले में है द्वारा उपयोग किया है BindingSource (ये सभी System.Windows.Forms नामस्थान में हैं)।

bindable गुण की खोज करने के लिए, CurrencyManager invokes ListBindingSource.GetListItemProperties। हुड के तहत, यह GetListItemPropertiesByInstance पर कॉल करता है (जब आप एक ही ऑब्जेक्ट में जाते हैं)। है

return TypeDescriptor.GetProperties(target, BrowsableAttributeList); 

और BrowsableAttributeList के कार्यान्वयन:: यह विधि अंत में कोड की निम्न पंक्ति है

private static Attribute[] BrowsableAttributeList 
{ 
    get 
    { 
     if (browsableAttribute == null) 
     { 
      browsableAttribute = new Attribute[] { new BrowsableAttribute(true) }; 
     } 
     return browsableAttribute; 
    } 
} 

आप देख सकते हैं यह है कि, वास्तव में, BrowsableAttribute(true) द्वारा गुण को छानने। यह शायद BindableAttribute का उपयोग करना चाहिए, लेकिन मेरा अनुमान यह है कि डिजाइनरों को एहसास हुआ कि हर कोई पहले से ही BrowsableAttribute पर निर्भर था और इसके बजाय इसका उपयोग करने का फैसला किया था।

दुर्भाग्यवश यदि आप BrowsableAttribute का उपयोग करते हैं तो आप इस समस्या को हल करने में सक्षम नहीं होंगे। आपके एकमात्र विकल्प या तो मार्क सुझाव देते हैं और कस्टम TypeConverter का उपयोग करते हैं, या इस प्रश्न में समाधानों में से किसी एक का उपयोग करके संपत्ति ग्रिड को स्वयं फ़िल्टर करते हैं: Programatically Hide Field in PropertyGrid

+0

हाँ, आप सही हैं। ऐसा लगता है कि काम करता है। मुझे एक बड़ी परियोजना में यह समस्या है। मैं जल्द ही एक बेहतर उदाहरण लिखने की कोशिश करूंगा। – bodziec

3

BrowsableAttribute का उपयोग कई घटक-मॉडल तरीके से किया जाता है ताकि इसे शामिल करने से बचने के लिए एक तंत्र के रूप में उपयोग किया जा सके। शायद सबसे अच्छा विकल्प [Browsable(false)] नहीं जोड़ना है।

वहाँ PropertyGrid छानने, (बढ़ती जटिलता में) TypeDescriptionProvider सहित TypeConverter, ICustomTypeDescriptor, के कई अन्य तरीके हैं - लेकिन सबसे सरल शायद PropertyGrid विशेषताओं है कि चीजें आप अभाव (.BrowsableAttributes) कर वर्णन बताओ, और चिह्नित करने के लिए है अन्य गुण

ध्यान दें कि दूसरा विकल्प कस्टम टैब बनाना है - लेकिन यह मेरे अनुभव में हिट नहीं है।

यहां TypeConverter का उपयोग करके एक उदाहरण दिया गया है, जिसका उपयोग PropertyGrid द्वारा किया जाता है, लेकिन अधिकांश अन्य बाइंडिंग द्वारा नहीं; यह एक कस्टम प्रकार कनवर्टर जो नाम से एक विशिष्ट संपत्ति बाहर निकाल देता होने से काम करता है, लेकिन आप यह भी Attribute.IsDefined की तरह कुछ इस्तेमाल कर सकते हैं मास्किंग करने के लिए:

using System.Windows.Forms; 
using System; 
using System.Linq; 
using System.ComponentModel; 
static class Program 
{ 
    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Data data = new Data { Name = "the name", Value = "the value" }; 
     using (Form form = new Form 
     { 
      Controls = 
      { 
       new PropertyGrid { 
        Dock = DockStyle.Fill, 
        SelectedObject = data 
       }, 
       new TextBox { 
        Dock = DockStyle.Bottom, 
        DataBindings = { {"Text", data, "Value"}, } 
       }, 
       new TextBox { 
        Dock = DockStyle.Bottom, 
        DataBindings = { {"Text", data, "Name"}, } 
       } 
      } 
     }) 
     { 
      Application.Run(form); 
     }   
    } 
} 
[TypeConverter(typeof(DataConverter))] 
class Data 
{ 
    class DataConverter : ExpandableObjectConverter 
    { 
     public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) 
     { 
      var props = base.GetProperties(context, value, attributes); 
      return new PropertyDescriptorCollection(
       (from PropertyDescriptor prop in props 
       where prop.Name != "Value" 
       select prop).ToArray(), true); 
     } 
    } 
    public string Value { get; set; } 
    public string Name { get; set; } 
} 

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^