Hi,
I am getting an error of "Key already exists" when trying to reuse an appearance object with the UltraGrid. Here is the scenario:
1. In the grid's Initialize_Layout method I have the following code to set up my appearance:
// cancel date appearance
if (!this.ugCommon.DisplayLayout.Appearances.Exists(CANCEL_DATE))
{
Infragistics.Win.Appearance cancelDateAppearance = this.ugCommon.DisplayLayout.Appearances.Add(CANCEL_DATE);
cancelDateAppearance.ForeColor = Color.Red;
}
2. My grid has a column called "Cancel Date". If today's date is greater than this value then I need to make the text of the entire row red. To do this I added some code to the InitializeRow event. I compare the dates and if I have to add the red coloring I am doing this:
foreach (UltraGridCell c in e.Row.Cells)
c.SelectedAppearance = this.ugCommon.DisplayLayout.Appearances[CANCEL_DATE];
c.Appearance = this.ugCommon.DisplayLayout.Appearances[CANCEL_DATE]; <== Problem Line of Code
The error occurs on the second line in the foreach loop:
c.Appearance = this.ugCommon.DisplayLayout.Appearances[CANCEL_DATE];
I am not sure what is going on here. I have to make sure both the appearance and the selected appearance have red text, so I need to change both.
Ok, thanks for looking into this. I appreciate your help! I'll use the second appearance object for now.
Thanks,
Steve
I took a look at the source code for the SetMulticastAppearance method and it looks like what you are experiencing here is an old bug that was fixed back in 2007.
I checked it out, and the fix for this issue was made to v6.2 and up. So you should just get the latest service release and that should fix it.
How to get the latest service release - Infragistics Community
If you cannot upgrade to the service release, then I guess you will have to use 2 identical appearance objects like you are doing. This is a bit inefficient, but it's only one extra appearance object, so it's not a big deal.
I switched the order that I assigned the appearance objects just to see, so this time I assign to the .Appearance first and the .SelectedAppearance second. I still get the same error. The actual error text with call stack is:
System.ArgumentException: Item has already been added. Key in dictionary: 'Infragistics.Win.UltraWinGrid.UltraGridCell' Key being added: 'Infragistics.Win.UltraWinGrid.UltraGridCell' at System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add) at System.Collections.Hashtable.Add(Object key, Object value) at Infragistics.Win.UltraWinGrid.UltraGridLayout.SetMulticastAppearance(AppearanceBase appearance, Object obj) at Infragistics.Win.UltraWinGrid.UltraGridCell.set_SelectedAppearance(AppearanceBase value) at Cigna.ES.Infrastructure.CompositeUI.User_Controls.CommonGrid.ugCommon_InitializeRow(Object sender, InitializeRowEventArgs e) in c:\valorsource\development\valorframework\latest\Cigna.ES.Infrastructure.CompositeUI.v1.0\User Controls\CommonGrid\CommonGrid.cs:line 3200 at Infragistics.Win.UltraWinGrid.UltraGrid.OnInitializeRow(InitializeRowEventArgs e) at Infragistics.Win.UltraWinGrid.UltraGrid.FireEvent(GridEventIds id, EventArgs e) at Infragistics.Win.UltraWinGrid.UltraGrid.FireInitializeRow(InitializeRowEventArgs e) at Infragistics.Win.UltraWinGrid.UltraGridRow.FireInitializeRow() at Infragistics.Win.UltraWinGrid.UltraGridCell.SetValue(Object value, Boolean suppressErrorMessagePrompt, Boolean fireInitializeRow, Boolean throwExceptionOnError) at Infragistics.Win.UltraWinGrid.UltraGridCell.SetValue(Object value, Boolean suppressErrorMessagePrompt, Boolean fireInitializeRow) at Infragistics.Win.UltraWinGrid.UltraGridCell.set_Value(Object value) at Cigna.ES.Infrastructure.CompositeUI.User_Controls.CommonGrid.SetCustomColumnValues() in c:\valorsource\development\valorframework\latest\Cigna.ES.Infrastructure.CompositeUI.v1.0\User Controls\CommonGrid\CommonGrid.cs:line 1163 at Cigna.ES.Infrastructure.CompositeUI.User_Controls.CommonGrid.InitialGridSetup() in c:\valorsource\development\valorframework\latest\Cigna.ES.Infrastructure.CompositeUI.v1.0\User Controls\CommonGrid\CommonGrid.cs:line 1123 at Cigna.ES.Infrastructure.CompositeUI.User_Controls.CommonGrid.ugCommon_InitializeLayout(Object sender, InitializeLayoutEventArgs e) in c:\valorsource\development\valorframework\latest\Cigna.ES.Infrastructure.CompositeUI.v1.0\User Controls\CommonGrid\CommonGrid.cs:line 2493 at Infragistics.Win.UltraWinGrid.UltraGrid.OnInitializeLayout(InitializeLayoutEventArgs e) at Infragistics.Win.UltraWinGrid.UltraGrid.FireEvent(GridEventIds id, EventArgs e) at Infragistics.Win.UltraWinGrid.UltraGrid.FireInitializeLayout(InitializeLayoutEventArgs e) at Infragistics.Win.UltraWinGrid.UltraGridLayout.ApplyLoadedBands() at Infragistics.Win.UltraWinGrid.UltraGridLayout.ListManagerUpdated(BindingManagerBase bindingManager) at Infragistics.Win.UltraWinGrid.UltraGridLayout.ListManagerUpdated() at Infragistics.Win.UltraWinGrid.UltraGridBase.Set_ListManager(Object newDataSource, String newDataMember) at Infragistics.Win.UltraWinGrid.UltraGridBase.DataBind() at Cigna.ES.Infrastructure.CompositeUI.User_Controls.CommonGrid.RebindData() in c:\valorsource\development\valorframework\latest\Cigna.ES.Infrastructure.CompositeUI.v1.0\User Controls\CommonGrid\CommonGrid.cs:line 880 at Cigna.ES.Infrastructure.NUnit.Controller.CommonGridView.SetupGridCustom(String pCount) in c:\valorsource\development\valorframework\latest\Cigna.ES.Infrastructure.NUnit.Controller\CommonGrid\CommonGridView.cs:line 204 at Cigna.ES.Infrastructure.NUnit.Controller.CommonGridView.btnBindGrid_Click(Object sender, EventArgs e) in c:\valorsource\development\valorframework\latest\Cigna.ES.Infrastructure.NUnit.Controller\CommonGrid\CommonGridView.cs:line 458 at System.Windows.Forms.Control.OnClick(EventArgs e) at Infragistics.Win.UltraControlBase.OnClick(EventArgs e) at Infragistics.Win.Misc.UltraButtonBase.OnClick(EventArgs e) at Infragistics.Win.Misc.UltraButton.OnMouseUp(MouseEventArgs e) at System.Windows.Forms.Control.WmMouseUp(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.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
I don't have this problem if I use two separate appearance objects and assign one to the .SelectedAppearance and the other to the .Appearance. I can just do that.
In reference to why I am assigning the appearance to each cell... I could not find a SelectedAppearance object off of the Row object. I only found it on the cell. I don't want to change the selected appearance for all rows in the grid, just the few that apply to my case. My company is still on version 6.2 of the grid :( so maybe there is a SelectedAppearance off of the row object in a later version. I wanted to make the changes at the row level, but couldn't figure it out. Is there a way to do this?
The "strange results" that I got when assigning the new appearance was that I lost some other appearance changes that I had made. I found a way to fix this though... I hope it is a good method. I access the style set and make a new Appearance object from my existing row appearance. Then I modify just the ForeColor. This way I am able to retain everything else about the "unmodified" Appearance. Here is the code I am using. I wrapped it in a method that returns my modified AppearanceBase object:
ApplicationStyleLibrary styleLib = new ApplicationStyleLibrary();StyleSetSettings styleSet = null;AppearanceBase appearance = null;
styleLib.LoadFromStyleManager();styleSet = styleLib.StyleSets.GetStyleSet("CommonGrid", false);
if(styleSet != null){ StyleSettings gridRowRole = styleSet.RoleStyles.GetStyle("GridRow", false);
if(gridRowRole != null) { StateSettings gridRowNormal = gridRowRole.States.GetState(RoleState.Normal, false);
if(gridRowNormal != null) { // create a new appearance base object to modify with the changes appearance = gridRowNormal.CreateAppearance(true, true, true); appearance.ForeColor = Color.Red; } }}
return appearance;
I don't see any way that the line of code you have here could possibly cause a "Key Already Exists" error message. That message indicates that you are attempting to add an item to a collection which already contains an item with the same key. But your code is not adding anything to a collection. you are just setting a property and indexing into an existing collection. Are you sure that's the right line of code? can you post the entire call stack of the error?
In any case, why are you assigning the appearance to each individual cell in the row? It would be a lot more efficient and a lot easier to simply assign the appearance to row, instead.
sw06226 said:When I create a new appearance and change the ForeColor to red I get strange results. I am guessing because the other appearance settings are lost on this new one.
I don't understand what you mean by this. What "strange results" are you getting?
There's no inheritance for Appearances, so you cannot base one appearance on another. But appearances are resolved in order of most specific to least specific, so generally you would only set some properties on the Appearance and the other settings come from somewhere else - ether another less specific appearance or an ultimate default value.