C# DataGrid Question



  • This problem is kicking my butt, I'm hoping some of you C# gurus out there can help me out. I've got a web form that contains a DataGrid full of addresses, which can either be populated with 'deleted' or 'active' addresses based on a DropDownList. Whenever the DropDownList's selected index changes, it fires the function to rebind the grid. What I'm trying to do is change the text of one of the ButtonColumns in the grid so that it says either 'delete' or 'undelete' depending on what addresses you're looking at. Here's the code that's called whenever an item is bound to the DataGrid:

    if (e.Item.ItemType != ListItemType.AlternatingItem && e.Item.ItemType != ListItemType.Item)
       return;
    if (address_picker.SelectedItem.Text == "Deleted")
    {
       ((ButtonColumn)address_grid.Columns[6]).Text = "Undelete";
       ((ButtonColumn)address_grid.Columns[6]).CommandName = "undelete";
    }
    else
    {
       ((ButtonColumn)address_grid.Columns[6]).Text = "Delete";
       ((ButtonColumn)address_grid.Columns[6]).CommandName = "delete";
    }

    Now the function that's called when the grid binds is dependant on address_picker.SelectedItem.Text as well, so I know that's not the issue. But after I delete an address and then change the index of the DropDownList, it will bind the correct addresses to the grid, but it WON'T change the text of the ButtonColumn unless I do something that will rebind the grids a second time (swapping between 'deleted' and 'active' still shows wrong text values, it's only when I rebind the grid on the same value of the DropDownList that it updates. And then it breaks again the next time I delete/undelete an address).

    Any ideas? I hope I'm being clear enough, the coffee hasn't kicked in yet. Or is there a better way I can do this?? Since the data the two address types (deleted/active) use are the same except for the wording of this button, I didn't want to use two separate grids (though it would solve this problem). Any help is appreciated, and I can elaborate if anyone needs me to. Thanks!



  • Which version of visual studio/.net are you using?  The datagrid is notriously annoying when you try to do anything beyond the rudimentary.  I'll take a look after work tonight and will probably have more questions for you then as I'm not completely clear on the issue. 

    also this may point you in the right direction. a coworker used it to reach into a datarid and access a checkbox directly.

     

    <FONT size=2 face=Arial><FONT color=#0000ff size=2><FONT color=#0000ff size=2>Function</FONT></FONT><FONT size=2> GetCheckBoxValues() </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>As</FONT></FONT><FONT size=2> Generic.List(</FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>Of</FONT></FONT><FONT size=2> </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>Integer</FONT></FONT><FONT size=2>)
    </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>     Dim</FONT></FONT><FONT size=2> myDataGridItem </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>As</FONT></FONT><FONT size=2> DataGridItem
         </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>Dim</FONT></FONT><FONT size=2> chkSelected </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>As</FONT></FONT><FONT size=2> System.Web.UI.WebControls.CheckBox
         </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>Dim</FONT></FONT><FONT size=2> strLocationNumber </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>As</FONT></FONT><FONT size=2> Generic.List(</FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>Of</FONT></FONT><FONT size=2> </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>Integer</FONT></FONT><FONT size=2>) = </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>New</FONT></FONT><FONT size=2> Generic.List(</FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>Of</FONT></FONT><FONT size=2> </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>Integer</FONT></FONT><FONT size=2>)</FONT></FONT></FONT><FONT size=2>

    </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>     For</FONT></FONT><FONT size=2> </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>Each</FONT></FONT><FONT size=2> myDataGridItem </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>In</FONT></FONT><FONT size=2> dgLocation.Items
              chkSelected = myDataGridItem.FindControl(</FONT><FONT color=#a31515 size=2><FONT color=#a31515 size=2>"chkLocation"</FONT></FONT><FONT size=2>)

    </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>          If</FONT></FONT><FONT size=2> chkSelected.Checked </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>Then
                   </FONT></FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>Dim</FONT></FONT><FONT size=2> lblTemp </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>As</FONT></FONT><FONT size=2> Label = </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>CType</FONT></FONT><FONT size=2>(myDataGridItem.FindControl(</FONT><FONT color=#a31515 size=2><FONT color=#a31515 size=2>"lblLocationNumber"</FONT></FONT><FONT size=2>), Label)
                   </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>Dim</FONT></FONT><FONT size=2> locNum </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>As</FONT></FONT><FONT size=2> </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>Integer</FONT></FONT><FONT size=2> = Convert.ToInt32(lblTemp.Text)</FONT></FONT><FONT size=2>

                   Console.WriteLine(</FONT><FONT color=#a31515 size=2><FONT color=#a31515 size=2>"Location ID: "</FONT></FONT><FONT size=2> & locNum.ToString())
                   strLocationNumber.Add(locNum)
              </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>End</FONT></FONT><FONT size=2> </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>If
         </FONT></FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>Next

    </FONT></FONT><FONT size=2>

    </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>     Return</FONT></FONT><FONT size=2> strLocationNumber
    </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>End</FONT></FONT><FONT size=2> </FONT><FONT color=#0000ff size=2><FONT color=#0000ff size=2>Function

    </FONT></FONT></FONT>


  • I'm using VS 2008 and the app is .NET 3.5. I just can't figure out why it's binding the correct data but not updating the ButtonColumn text... Any insight would rock



  • Just keeping this up to date, I tried to implement the changes in the DropDownList's index changed method:

    protected void address_picker_item_changed(object sender, EventArgs e)
    {
       foreach (DataGridColumn c in address_grid.Columns)
       {
          if (c.GetType() == typeof(ButtonColumn))
          {
             if (address_picker.SelectedItem.Text == "Deleted")
             {
                ((ButtonColumn)c).Text = "Undelete";
                ((ButtonColumn)c).CommandName = "undelete";
             }
             else if (address_picker.SelectedItem.Text == "Active")
             {
                ((ButtonColumn)c).Text = "Delete";
                ((ButtonColumn)c).CommandName = "delete";
             }
          }
       }
       update_address_grid();
    }

    Where update_address_grid() is the function that creates the DataSource and calls DataBind(). I tried that code both before and after the grid gets bound, both times it works exactly the same as before (it didn't update until I caused the grid to bind a second time). Now this is getting strange. I could see the change fouling up when the items are getting bound, just because the're working off the original data. But how the heck is this failing to change the Text/CommandNames the first time?

    Ugly solutions that would probably work are: Creating a second grid (ugh) or forcing the AutoPostback and let the grid bind a second time (double ugh)

     

    Side note: how the heck do I format my code so nice and pretty as above? I feel bad posting this black & white uglyness :/

     



  • if rebinding works I would recommend just doing that.  or you can manually do it using a variation on the code I just added to my post above.  The datagrid is probably the most finnicky control of them all. 

     So basically heres what I understand so far.

    1) you have a drop down that has two options: Active, Deleted as items

    2) when the user selects one two things need to happen:

         a) The data itself needs to be refreshed

         b) The command and button text need to be changed depending on what the user selected.



  • That's the long and the short of it. It sounds so trivial I can't believe I'm running into issues. Now my index changed function calls the same update_address_grid() funciton twice, and it works. UGH. If anyone comes across a better reason for this to be so... rediculous, let me know. This app isn't on such a huge scale that binding the data twice will make any tangible difference, I'll just have to live knowing there's a dirty, filthy hack in my (mostly) beautiful code :P



  •  

    I consider the datagrid antiquated compared to the GridView control.  The datagrid always seems to the source of many a dev's misery.  Another solution might be to use a datalist control instead.  Although easier to use in situations like this, it can sometimes be counter intuiative as well 


  • I'll have to play around with the GridView control a bit... thanks for the advice! In the mean time I'll just have to leave a note to come back to this code somewhere down the line and find a better solution :P



  • @SheepFister said:

    Any ideas? I hope I'm being clear enough, the coffee hasn't kicked in yet. Or is there a better way I can do this?? Since the data the two address types (deleted/active) use are the same except for the wording of this button, I didn't want to use two separate grids (though it would solve this problem). Any help is appreciated, and I can elaborate if anyone needs me to.

    I actually would use two separate grids: each grid located in its own user control. Then have the correct user control dynamically loaded into place based on the contents of the drop down list.

    Why separate grids? Because it scales infinitely better. You have two distinctly different processes, even if they do look and feel alike right now. Just watch one more option having to be added to that drop down list and watch it have a slightly different view on the same data...

    @galgorah said:

    I consider the datagrid antiquated compared to the GridView control. The datagrid always seems to the source of many a dev's misery. Another solution might be to use a datalist control instead. Although easier to use in situations like this, it can sometimes be counter intuiative as well

    I'd be careful with the datalist control. I know the asp.net 2.0 version of the control to render structurally invalid html. (Unclosed tags, inline level tags containing block level tags, etc.)



  • @Ragnax said:

    @SheepFister said:
    Any ideas? I hope I'm being clear enough, the coffee hasn't kicked in yet. Or is there a better way I can do this?? Since the data the two address types (deleted/active) use are the same except for the wording of this button, I didn't want to use two separate grids (though it would solve this problem). Any help is appreciated, and I can elaborate if anyone needs me to.

    I actually would use two separate grids: each grid located in its own user control. Then have the correct user control dynamically loaded into place based on the contents of the drop down list.

    Why separate grids? Because it scales infinitely better. You have two distinctly different processes, even if they do look and feel alike right now. Just watch one more option having to be added to that drop down list and watch it have a slightly different view on the same data...

    @galgorah said:
    I consider the datagrid antiquated compared to the GridView control. The datagrid always seems to the source of many a dev's misery. Another solution might be to use a datalist control instead. Although easier to use in situations like this, it can sometimes be counter intuiative as well

    I'd be careful with the datalist control. I know the asp.net 2.0 version of the control to render structurally invalid html. (Unclosed tags, inline level tags containing block level tags, etc.)

    Yes the datalist control can do such and often does.  but if you take that into account you can usually get by.  I hardly ever use it myself :)


  • @Ragnax said:

    I actually would use two separate grids: each grid located in its own user control. Then have the correct user control dynamically loaded into place based on the contents of the drop down list.

    Why separate grids? Because it scales infinitely better. You have two distinctly different processes, even if they do look and feel alike right now. Just watch one more option having to be added to that drop down list and watch it have a slightly different view on the same data...

     

    The reason I chose to not use two different grids was because the two processes were almost identical. Both grids contain identical information, and the delete/undelete ButtonColumn only flips a bit in the database. I can't see there ever being a third option for this grid, so in the event that my users want more information being bound to it, I'll only have to change one grid and one set of functions.

    If there was the chance that another process would pop up, or if these two weren't so much alike, I'd be using two grids no questions asked. And I'll look into the DataList control for 3.5 and see if they fixed any problems with it... I'm trying to keep all my HTML valid.



  • Make 2 seperate columns for delete and undelete, hide/show the correct column as needed.


Log in to reply