2009-07-23 4 views
2

Notre application DataGrid-heavy aime lancer des exceptions en double-cliquant sur l'espace entre les lignes utilisées pour le redimensionnement. L'exception est The " DataGridColumnStyle cannot be used because it is not associated with a Property or a Column in the DataSource.Comment gérer une exception provoquée par un double-clic entre les lignes d'un DataGrid?

La plupart de nos formulaires basés sur DataGrid héritent d'une forme appelée GridForm. Notre DataSource est un DataView. Je peux définir un point d'arrêt dans notre gestionnaire d'événements double-clic, mais il n'est jamais atteint. L'exception est interceptée à l'appel Show/ShowDialog de l'ensemble du formulaire hébergeant le contrôle. Nous exécutons maintenant .NET 3.5, mais la plupart de cette fonctionnalité a été construite dans .NET 1.1. Nous avons eu le même problème à l'époque.

StackOverflow propre de Joel Coehoorn semble avoir couru dans le même problème ici: http://discuss.fogcreek.com/dotnetquestions/default.asp?cmd=show&ixPost=5780

Ceci est un bug que nous avons eu rôdent autour d'un bon 3-4 ans, afin de résoudre ce serait incroyable.


Voici l'exception complète: Le DataGridColumnStyle dont il se plaint diffère entre chaque grille dans notre application. Je suppose que cela signifie que nous avons un style de colonne qui affiche une colonne qui n'est pas dans l'ensemble de données lié. Les colonnes incluses dans un ensemble de données changeront en fonction des besoins pour un formulaire donné, donc nous avons vraiment besoin de définir des styles pour les colonnes qui pourraient ou ne pourraient pas être là.

System.InvalidOperationException: DataGridColumnStyle of 'Real-Time Bill' cannot be used because it is not associated with a Property or Column in the DataSource. 
    at System.Windows.Forms.DataGridColumnStyle.CheckValidDataSource(CurrencyManager value) 
    at System.Windows.Forms.DataGridColumnStyle.GetColumnValueAtRow(CurrencyManager source, Int32 rowNum) 
    at System.Windows.Forms.DataGridBoolColumn.GetColumnValueAtRow(CurrencyManager lm, Int32 row) 
    at System.Windows.Forms.DataGrid.RowAutoResize(Int32 row) 
    at System.Windows.Forms.DataGrid.OnMouseDown(MouseEventArgs e) 
    at System.Windows.Forms.Control.WmMouseDown(Message& m, MouseButtons button, Int32 clicks) 
    at System.Windows.Forms.Control.WndProc(Message& m) 
    at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) 
    at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 
    at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 
    at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) 
    at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData) 
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) 
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) 
    at System.Windows.Forms.Application.Run(Form mainForm) 
    at CLS.Presentation.MainForm.Main(String[] args) in C:\Users\stuartb.CLS\Documents\Projects\Genesis\CLS.Presentation\MainForm.cs:line 2712 


Comme demandé, voici la définition de la colonne en question. Accordée, ce n'est pas toujours cette colonne que l'exception indique. Comme indiqué dans ma précédente modification, les styles de colonne qui recherchent une colonne qui n'est pas dans le DataTable lié provoquent ce problème. Dans cet exemple, ConsumptionBill est et non dans le DataTable lié. Le comportement dans ce cas consiste simplement à ne pas afficher la colonne, et apparemment se bloquer et graver sur les doubles-clics de bordure de ligne.

this.dataGridBoolColumnClientsConsumptionBill.Alignment = System.Windows.Forms.HorizontalAlignment.Center; 
this.dataGridBoolColumnClientsConsumptionBill.AllowNull = false; 
this.dataGridBoolColumnClientsConsumptionBill.HeaderText = "Real-Time Bill"; 
this.dataGridBoolColumnClientsConsumptionBill.MappingName = "ConsumptionBill"; 
this.dataGridBoolColumnClientsConsumptionBill.Width = 75; 

Répondre

3

Merci à creuser un peu guidé, avec l'aide de John, j'ai pu résoudre le problème en général avec la méthode suivante.

IList<DataGridColumnStyle> missingColumnStyles = new List<DataGridColumnStyle>(); 
/// <summary> 
/// Adjust the grid's definition to accept the given DataTable. 
/// </summary> 
/// <param name="table"></param> 
protected virtual void AdjustGridForData(DataTable table, DataGrid grid) 
{ 
    // Remove column styles whose mapped columns are missing. 
    // This fixes the notorious, uncatchable exception caused when double-clicking row borders. 
    var columnStyles = grid.TableStyles[table.TableName].GridColumnStyles; 

    // Add previously removed column styles back to the grid, in case the new bound table 
    // has something we removed last time this method was executed. 
    foreach (var missingColumnStyle in missingColumnStyles) 
     columnStyles.Add(missingColumnStyle); 
    missingColumnStyles.Clear(); 

    // Move the offending column styles into a separate list. 
    var missingColumns = new List<string>(); 
    foreach (DataGridColumnStyle style in columnStyles) 
    { 
     if (!table.Columns.Contains(style.MappingName)) 
      missingColumns.Add(style.MappingName); 
    } 
    foreach (var column in missingColumns) 
    { 
     missingColumnStyles.Add(columnStyles[column]); 
     columnStyles.Remove(columnStyles[column]); 
    } 
}