We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

GridGroupingControl general selection and position issues

I am having some basic issues with the GridGroupingControl with regards to basic row selection and currencymanager position. So basic in fact, that I am hoping that someone can clear up my mistakes. What I am trying to accomplish is simple (well at least for this discussion): I want a GridGroupingControl to clearly mark the selected row with a highlight (not just an arrow on the row header). When a row is selected I want some separate edit fields, on the same form, to hold the values from the selected row. NOTE: I will utilize the FirstGridGroupCtl sample to describe these issues ------------- Issues: 1.) After some reading, someone suggested that I could get the highlight row selection behavior I want by setting the ListBoxSelectionMode to One. So using the FirstGridGroupCtl sample, simply go into the designer on Form1, select the gridGroupingControl1, go down to TableDescriptor->TableOptions->ListBoxSelectionMode and set this to "One". Now run the sample. Group by School (or any column) by simply dragging the school header up to the GridGroupDropArea. Now expand a group. Now select one of the records in that group. Now expand another group. You will notice that the selected record highlight does not move with the selected record. It appears to stay in the same row no matter what is in that row after you expand/collapse a group. Is there a way to fix this? 2.) So then I decided to go the route of maintaining my own highlight of the selected row (which seems like something I should not have to do manually). First take off the ListBoxSelectionMode property we set in the first step. Then, going by the info I found in the forums, I added the following code (you can easily add it to the FirstGridGroupCtl sample) : this.gridGroupingControl1.TableControlPrepareViewStyleInfo += new GridTableControlPrepareViewStyleInfoEventHandler(this.gridGroupingControl1_PrepareViewStyleInfo); private void gridGroupingControl1_PrepareViewStyleInfo(object sender, GridTableControlPrepareViewStyleInfoEventArgs e) { GridTableCellStyleInfo style = (GridTableCellStyleInfo) e.Inner.Style; if (style.TableCellIdentity.TableCellType == GridTableCellType.RecordFieldCell || style.TableCellIdentity.TableCellType == GridTableCellType.AlternateRecordFieldCell) { Record r = style.TableCellIdentity.DisplayElement.ParentRecord; if (r.IsCurrent) { if (this.gridGroupingControl1.TableControl.CurrentCell.ColIndex != style.TableCellIdentity.ColIndex || this.gridGroupingControl1.TableControl.CurrentCell.RowIndex != style.TableCellIdentity.RowIndex) { e.Inner.Style.Borders.All = new GridBorder(GridBorderStyle.Solid, SystemColors.Highlight); e.Inner.Style.BackColor = SystemColors.Highlight; e.Inner.Style.TextColor = SystemColors.HighlightText; } } } } This seemed to work, but if you group by school again (or any column), then select a record, then click on any +/- to expand or collapse any group, the selected record is lost. That is nothing is selected anymore even though all I did was, for example, expand a completely unrelated group. So my selected record may not have ever even lost visibility, I might have just expanded another group, but that action alone clears the selected record. I am just living with this behavior now but it doesn''t seem like it should work that way (not to mention having to draw my own highlighting when I select a row which you don''t have to do in the GridDataBoundGrid for example). Is there a way to prevent the selected records from getting lost when you expand/collapse a group? 3.) Lastly, I have some edit fields databound to the same datasource and fields that are in the gridgroupingcontrol. However when I select a row in the GridGroupingControl, it does not update the position of the CurrencyManager. (this is default behavior for the standard windows DataGrid and I believe it works that way on the GridDataBoundGrid). The position is always on the first record unless I specifically move it. So I had to add the following code: this.gridGroupingControl1.Table.CurrentRecordContextChange += new CurrentRecordContextChangeEventHandler(this.gridGroupingControl1_CurrentRecordContextChange); private void gridGroupingControl1_CurrentRecordContextChange(object sender, CurrentRecordContextChangeEventArgs e) { // this is used to synchronize the other data grids with selected orders (meds, ordered by, etc..) if (e.Action == CurrentRecordAction.EnterRecordComplete) { // get the CurrentRecord here.. // loop through all the records in CurrencyManager.List ... // when I find a matching record, set CurrencyManager.Position to the matching record } } Once I set the CurrrencyManager.Position then of course the edit fields change appropriately to reflect the new record selection in the GridGroupingControl. Without this code, CurrencyManager.Position is always = 0. But this seems like another kluge, shouldn''t the position just change when I select the record? (The way the standard Datagrid does) At the very least, if I have to do it manually, is there a faster way than looping through every record until I find a match? ---------- I guess the bottom line is that it seems like I have lots of code to handle what seem to be basic tasks (in this case selection and position), and even then they do not work exactly like I would like. Any ideas on how I could fix these particular issues? Thanks, Brian

14 Replies

AD Administrator Syncfusion Team October 25, 2004 09:00 PM UTC

The upcoming 3.0 release has new selection support in it, so hopefully some of these problems will go away in that release. For now, attached is a sample that I think handles these problems. It uses the CurrencyManager.PositionChanged event to track teh currentposition. It then checks the record in PrepareViewStyleInfo to see if it is the current record from the currencymanager. The sample also has textboxes on the form that track the current row. GGCHightCurrentRow_5177.zip


BW Brian Wright October 26, 2004 03:57 PM UTC

Thanks for the response. However, the CurrencyManager.PositionChanged event never fires for my GridGroupingControl. As I mentioned, the position is always = 0 unless I specifically set it. This is what I am having to do today. My pseudo-code shows how I am having to trap the CurrentRecordContextChange event, find the position of that record, and then set the CurrencyManager.Position manually. Any idea why the CurrencyManager.Position is not changing on mine? >The upcoming 3.0 release has new selection support in it, so hopefully some of these problems will go away in that release. > >For now, attached is a sample that I think handles these problems. It uses the CurrencyManager.PositionChanged event to track teh currentposition. It then checks the record in PrepareViewStyleInfo to see if it is the current record from the currencymanager. The sample also has textboxes on the form that track the current row. > >GGCHightCurrentRow_5177.zip > >


AD Administrator Syncfusion Team October 26, 2004 04:16 PM UTC

If your currencymanager is not firing, then the currencymanager you are working with and the one the grid is using are likely not the same object. You will note the above sample was setting grid.DataSource = dt and was using the this.BindingContext[dt] to retrieve the currencymanager (if I recall correctly). This assumes the grid is using the same binding context as the form. If you have your grid embbeded in some other container than the form, this may not be the case. If you can post a sample project showing the problem, maybe we can suggest a way to get them synced up.


BW Brian Wright October 26, 2004 05:00 PM UTC

Here is the simplest sample I could make quickly. (Oddly unrelated, is the fact that I cannot group by any of the columns by dropping them on the GroupGridDropArea.. they all seem to not allow the drop. If you could let me know why that is it would be interesting) In this sample, I have tried to bind the CurrencyManager.PositionChanged event two different ways to make sure. Neither fire. Just select different rows and the event never fires. NOTE: This assumes you just put it into the project you already sent and change the static main in your Form1 to instantiate Form2 instead. >If your currencymanager is not firing, then the currencymanager you are working with and the one the grid is using are likely not the same object. > >You will note the above sample was setting grid.DataSource = dt and was using the this.BindingContext[dt] to retrieve the currencymanager (if I recall correctly). This assumes the grid is using the same binding context as the form. If you have your grid embbeded in some other container than the form, this may not be the case. If you can post a sample project showing the problem, maybe we can suggest a way to get them synced up. Form2_1003.zip


BW Brian Wright October 26, 2004 05:09 PM UTC

Hang on a sec.. somehow my gridGroupingControl1.DataMember got wiped out.. it should be in the code gridGroupingControl1.DataMember = "Table1" and then my event fires and I can group by the columns again. Not sure how I wiped it out but I am sure set it. let me see if I can keep adding the my sample to make it stop working. >Here is the simplest sample I could make quickly. (Oddly unrelated, is the fact that I cannot group by any of the columns by dropping them on the GroupGridDropArea.. they all seem to not allow the drop. If you could let me know why that is it would be interesting) > >In this sample, I have tried to bind the CurrencyManager.PositionChanged event two different ways to make sure. Neither fire. Just select different rows and the event never fires. > >NOTE: This assumes you just put it into the project you already sent and change the static main in your Form1 to instantiate Form2 instead. > > > >>If your currencymanager is not firing, then the currencymanager you are working with and the one the grid is using are likely not the same object. >> >>You will note the above sample was setting grid.DataSource = dt and was using the this.BindingContext[dt] to retrieve the currencymanager (if I recall correctly). This assumes the grid is using the same binding context as the form. If you have your grid embbeded in some other container than the form, this may not be the case. If you can post a sample project showing the problem, maybe we can suggest a way to get them synced up. > >Form2_1003.zip > >


BW Brian Wright October 27, 2004 05:26 PM UTC

Okay, attached is the simplest example of CurrencyManager.PositionChanged not firing that I could write. It turns out that for this to occur, 2 things have to happen (which made it harder to isolate): 1. The datasource must be a strongly typed dataset 2. You have to explictly add the columns such as: this.gridGroupingControl1.TableDescriptor.Columns.AddRange(new Syncfusion.Windows.Forms.Grid.Grouping.GridColumnDescriptor[] { new Syncfusion.Windows.Forms.Grid.Grouping.GridColumnDescriptor("col1"), new Syncfusion.Windows.Forms.Grid.Grouping.GridColumnDescriptor("col2")}); I have to add my columns in my original as I need to customize the decriptors for combobox columns, etc.. I know this seems weird and does not seem like it would have any affect on the ability for the currency manager to update new positions, but it does. Please check out my new form by adding it to your original sample and changing the static main to instantiate "GGCHightCurrentRow.Form3" The attached schema file needs to have the following properties set in the designer to auto build the strongly typed dataset: Custom Tool: MSDataSetGenerator Custom Tool Namespace: GGCHightCurrentRow (I just used the namespace from your original project) If you do not do both of these steps I described, then the position will update just fine. (i.e. create a dataset manually or just let the columns create themselves) Please let me know if you come up with a work around. Thanks, Brian >Hang on a sec.. somehow my gridGroupingControl1.DataMember got wiped out.. > >it should be in the code >gridGroupingControl1.DataMember = "Table1" > >and then my event fires and I can group by the columns again. Not sure how I wiped it out but I am sure set it. > >let me see if I can keep adding the my sample to make it stop working. > > >>Here is the simplest sample I could make quickly. (Oddly unrelated, is the fact that I cannot group by any of the columns by dropping them on the GroupGridDropArea.. they all seem to not allow the drop. If you could let me know why that is it would be interesting) >> >>In this sample, I have tried to bind the CurrencyManager.PositionChanged event two different ways to make sure. Neither fire. Just select different rows and the event never fires. >> >>NOTE: This assumes you just put it into the project you already sent and change the static main in your Form1 to instantiate Form2 instead. >> >> >> >>>If your currencymanager is not firing, then the currencymanager you are working with and the one the grid is using are likely not the same object. >>> >>>You will note the above sample was setting grid.DataSource = dt and was using the this.BindingContext[dt] to retrieve the currencymanager (if I recall correctly). This assumes the grid is using the same binding context as the form. If you have your grid embbeded in some other container than the form, this may not be the case. If you can post a sample project showing the problem, maybe we can suggest a way to get them synced up. >> >>Form2_1003.zip >> >> sample_2947.zip


BW Brian Wright October 27, 2004 05:29 PM UTC

I am having trouble with sentences getting truncated when I paste them into the post box so I reposting this message. Okay, attached is the simplest example of CurrencyManager.PositionChanged not firing that I could write. It turns out that for this to occur, 2 things have to happen (which made it harder to isolate): 1. The datasource must be a strongly typed dataset 2. You have to explictly add the columns such as: this.gridGroupingControl1.TableDescriptor.Columns.AddRange(new Syncfusion.Windows.Forms.Grid.Grouping.GridColumnDescriptor[] { new Syncfusion.Windows.Forms.Grid.Grouping.GridColumnDescriptor("col1"), new Syncfusion.Windows.Forms.Grid.Grouping.GridColumnDescriptor("col2")}); I have to add my columns in my original as I need to customize the decriptors for combobox columns, etc.. I know this seems weird and does not seem like it would have any affect on the ability for the currency manager to update new positions, but it does. Please check out my new form by adding it to your original sample and changing the static main to instantiate "GGCHightCurrentRow.Form3" The attached schema file needs to have the following properties set in the designer to auto build the strongly typed dataset: Custom Tool: MSDataSetGenerator Custom Tool Namespace: GGCHightCurrentRow (I just used the namespace from your original project) If you do not do both of these steps I described, then the position will update just fine. (i.e. create a dataset manually or just let the columns create themselves) Please let me know if you come up with a work around. Thanks, Brian >Okay, attached is the simplest example of CurrencyManager.PositionChanged not firing that I could write. > >It turns out that for this to occur, 2 things have to happen (which made it harder to isolate): > > >1. The datasource must be a strongly typed dataset > > >2. You have to explictly add the columns such as: > >this.gridGroupingControl1.TableDescriptor.Columns.AddRange(new Syncfusion.Windows.Forms.Grid.Grouping.GridColumnDescriptor[] { >new Syncfusion.Windows.Forms.Grid.Grouping.GridColumnDescriptor("col1"), >new Syncfusion.Windows.Forms.Grid.Grouping.GridColumnDescriptor("col2")}); > >I have to add my columns in my original as I need to customize the decriptors for combobox columns, etc.. > > > > >I know this seems weird and does not seem like it would have any affect on the ability for the currency manager to update new positions, but it does. > >Please check out my new form by adding it to your original sample and changing the static main to instantiate "GGCHightCurrentRow.Form3" > >The attached schema file needs to have the following properties set in the designer to auto build the strongly typed dataset: >Custom Tool: MSDataSetGenerator >Custom Tool Namespace: GGCHightCurrentRow > >(I just used the namespace from your original project) > >If you do not do both of these steps I described, then the position will update just fine. (i.e. create a dataset manually or just let the columns create themselves) > >Please let me know if you come up with a work around. > > >Thanks, > >Brian > > >>Hang on a sec.. somehow my gridGroupingControl1.DataMember got wiped out.. >> >>it should be in the code >>gridGroupingControl1.DataMember = "Table1" >> >>and then my event fires and I can group by the columns again. Not sure how I wiped it out but I am sure set it. >> >>let me see if I can keep adding the my sample to make it stop working. >> >> >>>Here is the simplest sample I could make quickly. (Oddly unrelated, is the fact that I cannot group by any of the columns by dropping them on the GroupGridDropArea.. they all seem to not allow the drop. If you could let me know why that is it would be interesting) >>> >>>In this sample, I have tried to bind the CurrencyManager.PositionChanged event two different ways to make sure. Neither fire. Just select different rows and the event never fires. >>> >>>NOTE: This assumes you just put it into the project you already sent and change the static main in your Form1 to instantiate Form2 instead. >>> >>> >>> >>>>If your currencymanager is not firing, then the currencymanager you are working with and the one the grid is using are likely not the same object. >>>> >>>>You will note the above sample was setting grid.DataSource = dt and was using the this.BindingContext[dt] to retrieve the currencymanager (if I recall correctly). This assumes the grid is using the same binding context as the form. If you have your grid embbeded in some other container than the form, this may not be the case. If you can post a sample project showing the problem, maybe we can suggest a way to get them synced up. >>> >>>Form2_1003.zip >>> >>> > >sample_2947.zip > > sample_9799.zip


BW Brian Wright October 27, 2004 05:32 PM UTC

Apparently when you paste a message into your post form, the sentences show up in their entirety, but any sentences longer than 80 chars or so are just truncated. So for the last time I hope, here is the whole post with complete sentences Okay, attached is the simplest example of CurrencyManager.PositionChanged not firing that I could write. It turns out that for this to occur, 2 things have to happen (which made it harder to isolate): 1. The datasource must be a strongly typed dataset 2. You have to explictly add the columns such as: this.gridGroupingControl1.TableDescriptor.Columns.AddRange( new Syncfusion.Windows.Forms.Grid.Grouping.GridColumnDescriptor[] { new Syncfusion.Windows.Forms.Grid.Grouping.GridColumnDescriptor("col1"), new Syncfusion.Windows.Forms.Grid.Grouping.GridColumnDescriptor("col2")}); I have to add my columns in my original as I need to customize the decriptors for combobox columns, etc.. I know this seems weird and does not seem like it would have any affect on the ability for the currency manager to update new positions, but it does. Please check out my new form by adding it to your original sample and changing the static main to instantiate "GGCHightCurrentRow.Form3" The attached schema file needs to have the following properties set in the designer to auto build the strongly typed dataset: Custom Tool: MSDataSetGenerator Custom Tool Namespace: GGCHightCurrentRow (I just used the namespace from your original project) If you do not do both of these steps I described, then the position will update just fine. (i.e. create a dataset manually or just let the columns create themselves) Please let me know if you come up with a work around. Thanks, Brian >I am having trouble with sentences getting truncated when I paste them into the post box so I reposting this message. > >Okay, attached is the simplest example of CurrencyManager.PositionChanged not firing that I could write. > >It turns out that for this to occur, 2 things have to happen (which made it harder to isolate): > > >1. The datasource must be a strongly typed dataset > > >2. You have to explictly add the columns such as: > >this.gridGroupingControl1.TableDescriptor.Columns.AddRange(new Syncfusion.Windows.Forms.Grid.Grouping.GridColumnDescriptor[] { >new Syncfusion.Windows.Forms.Grid.Grouping.GridColumnDescriptor("col1"), >new Syncfusion.Windows.Forms.Grid.Grouping.GridColumnDescriptor("col2")}); > >I have to add my columns in my original as I need to customize the decriptors for combobox columns, etc.. > > > > >I know this seems weird and does not seem like it would have any affect on the ability for the currency manager to update new positions, but it does. > >Please check out my new form by adding it to your original sample and changing the static main to instantiate "GGCHightCurrentRow.Form3" > >The attached schema file needs to have the following properties set in the designer to auto build the strongly typed dataset: >Custom Tool: MSDataSetGenerator >Custom Tool Namespace: GGCHightCurrentRow > >(I just used the namespace from your original project) > >If you do not do both of these steps I described, then the position will update just fine. (i.e. create a dataset manually or just let the columns create themselves) > >Please let me know if you come up with a work around. > > >Thanks, > >Brian > >>Okay, attached is the simplest example of CurrencyManager.PositionChanged not firing that I could write. >> >>It turns out that for this to occur, 2 things have to happen (which made it harder to isolate): >> >> >>1. The datasource must be a strongly typed dataset >> >> >>2. You have to explictly add the columns such as: >> >>this.gridGroupingControl1.TableDescriptor.Columns.AddRange(new Syncfusion.Windows.Forms.Grid.Grouping.GridColumnDescriptor[] { >>new Syncfusion.Windows.Forms.Grid.Grouping.GridColumnDescriptor("col1"), >>new Syncfusion.Windows.Forms.Grid.Grouping.GridColumnDescriptor("col2")}); >> >>I have to add my columns in my original as I need to customize the decriptors for combobox columns, etc.. >> >> >> >> >>I know this seems weird and does not seem like it would have any affect on the ability for the currency manager to update new positions, but it does. >> >>Please check out my new form by adding it to your original sample and changing the static main to instantiate "GGCHightCurrentRow.Form3" >> >>The attached schema file needs to have the following properties set in the designer to auto build the strongly typed dataset: >>Custom Tool: MSDataSetGenerator >>Custom Tool Namespace: GGCHightCurrentRow >> >>(I just used the namespace from your original project) >> >>If you do not do both of these steps I described, then the position will update just fine. (i.e. create a dataset manually or just let the columns create themselves) >> >>Please let me know if you come up with a work around. >> >> >>Thanks, >> >>Brian >> >> >>>Hang on a sec.. somehow my gridGroupingControl1.DataMember got wiped out.. >>> >>>it should be in the code >>>gridGroupingControl1.DataMember = "Table1" >>> >>>and then my event fires and I can group by the columns again. Not sure how I wiped it out but I am sure set it. >>> >>>let me see if I can keep adding the my sample to make it stop working. >>> >>> >>>>Here is the simplest sample I could make quickly. (Oddly unrelated, is the fact that I cannot group by any of the columns by dropping them on the GroupGridDropArea.. they all seem to not allow the drop. If you could let me know why that is it would be interesting) >>>> >>>>In this sample, I have tried to bind the CurrencyManager.PositionChanged event two different ways to make sure. Neither fire. Just select different rows and the event never fires. >>>> >>>>NOTE: This assumes you just put it into the project you already sent and change the static main in your Form1 to instantiate Form2 instead. >>>> >>>> >>>> >>>>>If your currencymanager is not firing, then the currencymanager you are working with and the one the grid is using are likely not the same object. >>>>> >>>>>You will note the above sample was setting grid.DataSource = dt and was using the this.BindingContext[dt] to retrieve the currencymanager (if I recall correctly). This assumes the grid is using the same binding context as the form. If you have your grid embbeded in some other container than the form, this may not be the case. If you can post a sample project showing the problem, maybe we can suggest a way to get them synced up. >>>> >>>>Form2_1003.zip >>>> >>>> >> >>sample_2947.zip >> >> > >sample_9799.zip > > sample_5079.zip


AD Administrator Syncfusion Team October 27, 2004 06:57 PM UTC

Try this code. CurrencyManager cm = this.gridGroupingControl1.Table.GetCurrencyManager(); cm.PositionChanged += new EventHandler(cm_PositionChanged);


BW Brian Wright October 29, 2004 12:05 PM UTC

This was a no-go as well. If you add what you sent me to my sample it should show this. Once again, it just seems that if you have a strongly typed dataset and if you explicitly add columns, then the CurrencyManager.Position will not get updated when you select different rows in the GridGroupingControl. If you do not do both, then it will work fine. Check out my sample and please let me know if there is a workaround or something that I am doing wrong. Thanks, Brian >Try this code. > >CurrencyManager cm = this.gridGroupingControl1.Table.GetCurrencyManager(); >cm.PositionChanged += new EventHandler(cm_PositionChanged); >


BW Brian Wright October 29, 2004 12:16 PM UTC

Doh! This did work. Thanks for the help. Not sure what I did earlier. Thanks for the help. Brian >This was a no-go as well. > >If you add what you sent me to my sample it should show this. > >Once again, it just seems that if you have a strongly typed dataset and if you explicitly add columns, then the CurrencyManager.Position will not get updated when you select different rows in the GridGroupingControl. > >If you do not do both, then it will work fine. > >Check out my sample and please let me know if there is a workaround or something that I am doing wrong. > >Thanks, > >Brian > > > > >>Try this code. >> >>CurrencyManager cm = this.gridGroupingControl1.Table.GetCurrencyManager(); >>cm.PositionChanged += new EventHandler(cm_PositionChanged); >>


BW Brian Wright October 29, 2004 01:28 PM UTC

Okay, I have one last issue. While your code did allow me to catch event notifications when the position changed, my original request called for some separate textboxes to hold values from the currently selected row. Any idea on what databindings I can give those textboxes so that they change values whenever a new record is selected? Just binding it with something like: this.textBox1.DataBindings.Add( new System.Windows.Forms.Binding("Text", this.dataSet1, "element1.col1")); does not work as it has a completely different CurrencyManager than the one obtained by: CurrencyManager cm = this.gridGroupingControl1.Table.GetCurrencyManager(); So when I add the event handler: cm.PositionChanged += new EventHandler(cm_PositionChanged); I get notified, but the textbox does not update any values because its CurrencyManager''s position never got updated. Thanks, Brian >Doh! > >This did work. Thanks for the help. > >Not sure what I did earlier. > >Thanks for the help. > >Brian > > >>This was a no-go as well. >> >>If you add what you sent me to my sample it should show this. >> >>Once again, it just seems that if you have a strongly typed dataset and if you explicitly add columns, then the CurrencyManager.Position will not get updated when you select different rows in the GridGroupingControl. >> >>If you do not do both, then it will work fine. >> >>Check out my sample and please let me know if there is a workaround or something that I am doing wrong. >> >>Thanks, >> >>Brian >> >> >> >> >>>Try this code. >>> >>>CurrencyManager cm = this.gridGroupingControl1.Table.GetCurrencyManager(); >>>cm.PositionChanged += new EventHandler(cm_PositionChanged); >>>


AD Administrator Syncfusion Team October 29, 2004 02:31 PM UTC

In the ListChanged event, you can sync up the Position property of each of the two CurrencyManagers being used. Here is you sample back, an dit seems to be working OK. GGCHightCurrentRow_7221.zip


BW Brian Wright October 29, 2004 02:51 PM UTC

This seems to solve it for me. Thanks for all the help and I am sorry for the very long thread. >In the ListChanged event, you can sync up the Position property of each of the two CurrencyManagers being used. Here is you sample back, an dit seems to be working OK. > >GGCHightCurrentRow_7221.zip > >

Loader.
Up arrow icon