2016-02-09 87 views
5

Inserisco uno DataGridView in un UserControl e creo una proprietà pubblica nel mio usercontrol che espone la proprietà delle colonne di datagridview.
Ecco il codice di esempio:L'esposizione della proprietà delle colonne di DataGridView in UserControl non funziona correttamente

public partial class UserControl1 : UserControl 
{ 
    public UserControl1() 
    { 
     InitializeComponent(); 
    } 

    public DataGridViewColumnCollection MyDataGridColumns 
    { 
     get 
     { 
      return dataGridView1.Columns; 
     } 
    } 
} 

poi aggiungo UserControl1 nella mia forma e clicco su MyDataGridColumns proprietà a finestra delle proprietà e aggiungere 1 o più colonne. Il problema si verifica quando ricostruisco la mia soluzione; Tutte le colonne che ho appena aggiunto scompaiono dopo la ricostruzione.

Qualcuno può spiegarmi perché questo accade? e come risolverlo?

+0

Come stai aggiungendo le colonne? In modalità progettazione o programmaticamente? –

+0

In modalità progettazione. –

+0

Prova ad aggiungere un setter alla tua proprietà 'MyDataGridColumns'. – Bioukh

risposta

4

Questo funziona per me: ho creato un editor di colonne specifico in quanto sembra impossibile utilizzare l'editor di colonne predefinito per qualsiasi controllo che non si estende DataGridView.

public partial class UserControl1 : UserControl, IDataGridView 
{ 
    public UserControl1() 
    { 
     InitializeComponent(); 
    } 

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
    [Browsable(false)] 
    public DataGridView DataGridView 
    { 
     get { return dataGridView1; } 
    } 

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 
    [Editor(typeof(ExtendedDataGridViewColumnCollectionEditor), typeof(UITypeEditor))] 
    [MergableProperty(false)] 
    public DataGridViewColumnCollection MyDataGridColumns 
    { 
     get { return dataGridView1.Columns; } 
    } 

} 

public interface IDataGridView 
{ 
    DataGridView DataGridView { get; } 
} 

class ExtendedDataGridViewColumnCollectionEditor : UITypeEditor 
{ 
    private Form dataGridViewColumnCollectionDialog; 

    private ExtendedDataGridViewColumnCollectionEditor() { } 

    private static Form CreateColumnCollectionDialog(IServiceProvider provider) 
    { 
     var assembly = Assembly.Load(typeof(ControlDesigner).Assembly.ToString()); 
     var type = assembly.GetType("System.Windows.Forms.Design.DataGridViewColumnCollectionDialog"); 

     var ctr = type.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance)[0]; 
     return (Form)ctr.Invoke(new object[] { provider }); 
    } 

    public static void SetLiveDataGridView(Form form, DataGridView grid) 
    { 
     var mi = form.GetType().GetMethod("SetLiveDataGridView", BindingFlags.NonPublic | BindingFlags.Instance); 
     mi.Invoke(form, new object[] { grid }); 
    } 

    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) 
    { 
     if (provider != null && context != null) 
     { 
      var service = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService)); 
      if (service == null || context.Instance == null) 
       return value; 

      var host = (IDesignerHost)provider.GetService(typeof(IDesignerHost)); 
      if (host == null) 
       return value; 

      if (dataGridViewColumnCollectionDialog == null) 
       dataGridViewColumnCollectionDialog = CreateColumnCollectionDialog(provider); 

      //Unfortunately we had to make property which returns inner datagridview 
      //to access it here because we need to pass DataGridView into SetLiveDataGridView() method 
      var grid = ((IDataGridView)context.Instance).DataGridView; 
      //we have to set Site property because it will be accessed inside SetLiveDataGridView() method 
      //and by default it's usually null, so if we do not set it here, we will get exception inside SetLiveDataGridView() 
      var oldSite = grid.Site; 
      grid.Site = ((UserControl)context.Instance).Site; 
      //execute SetLiveDataGridView() via reflection 
      SetLiveDataGridView(dataGridViewColumnCollectionDialog, grid); 

      using (var transaction = host.CreateTransaction("DataGridViewColumnCollectionTransaction")) 
      { 
       if (service.ShowDialog(dataGridViewColumnCollectionDialog) == DialogResult.OK) 
        transaction.Commit(); 
       else 
        transaction.Cancel(); 
      } 
      //we need to set Site property back to the previous value to prevent problems with serializing our control 
      grid.Site = oldSite; 
     } 

     return value; 
    } 

    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) 
    { 
     return UITypeEditorEditStyle.Modal; 
    } 
} 
2

Questo perché non è stato specificato il tipo di colonna. Si dovrebbe indicare il tipo di colonna quando si aggiunge una colonna (ad esempio DataGridViewTextBoxColumn o DataGridViewCheckBoxColumn). Nel tuo Form1.cs procedi come segue:

public Form1() 
{ 
    InitializeComponent(); 
    DataGridViewColumn dgViewColumn = new DataGridViewTextBoxColumn();//Or DataGridViewCheckBoxColumn 
    dgViewColumn.DataPropertyName = "dgViewColumn"; 
    dgViewColumn.HeaderText = @"dgViewColumn"; 
    dgViewColumn.Name = "dgViewColumn"; 
    userControl11.MyDataGridColumns.Add(dgViewColumn); 
} 
+2

@Afshin Aghazadeh, perché insisti a usare il designer? Il codice offre molto più controllo rispetto al progettista. – Oceans