Link to home
Start Free TrialLog in
Avatar of gailhl
gailhlFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Get the value from a cell in a detailsview row without knowing the index

Hi Experts,
   I need to do something like this:

        If  personDetails.Rows(16).Cells(0).Text = "some text" Then  ...

  But rather than referring to rows(16), I'd like to be able to refer to Rows("columnName").
  This should be easy but I can't find it!  Is there a way of doing this?

Thanks!
Gail HL
Avatar of GavinMannion
GavinMannion

I don't think you can.

Since all rows are the same you cannot give it a name.

I think you are getting confused between columns and rows.

Rows are vertical and columns horizontal.
Avatar of gailhl

ASKER

Thanks for your reply, Gavin ...

I don't think I am mixing up columns and rows, just sloppy in wording the question.  
The above example I gave works  - the problem with it is that it means any time a new field is added to the DetailsView, I've got to remember to change the code to reflect the new position of "rows(16)".  So I'd rather refer to it by some sort of key name, and as so much else in .NET is based on dictionaries, I'm guessing that the detailsview control might have keys somewhere that I can access, if only I knew the syntax.

Thanks,
Gail HL
I just did a quick test on my machine and to me Rows is the collection of DataRows in the details view.

So if I have 10 records returned I get 10 rows. It doesn't care about me changing the amount of fields returned only that amount or records.

I still say you cannot give the rows object a name instead of an index.
Avatar of gailhl

ASKER

Sorry, I still think we aren't talking about the same thing.
I'm talking about the new DetailsView control in ASP.Net 2.0, Visual Studio 2005.

There is only one row in a detailsview.  Its "rows" (as referred to in original question) are actually the "columns" of the underlying "table" (or dataview).  In other words, the rows and columns are inverted in the detailsview control.
Therefore, rows(16) refers to the value in the 15th column (0 based) for the one record which is bound to the detailsview.  Whenever I add a new column to the stored procedure that is the source of the data, the number of items in the rows collection will change.

So if I want to base a condition on the value in that field for that single record, I have to use the syntax
               If  personDetails.Rows(16).Cells(0).Text = "some text" Then  ...

But that's dodgy because at some future point, if the underlying procedure is changed, that field could be in rows(17) rows(23) -- in the detailsview control, that is (not in the underlying table).  

But being a bit of a newbie to ASP.NET and to Visual Studio 2005, I don't actually know how to query the value in the cell any other way (I don't know the syntax for querying the underlying data before the detailsview control inverts it).
But I'm guessing that there probably IS a better way than what I am doing.

Thanks
Gail HL
Okay lets just ignore the row section :)

You are worried that the SQL will change which will then stop you code from working?

Easiest way to avoid this, which I would always recommend you do, is to be specific about what you want to display. For example
<asp:DetailsView    DataSourceID="DetailsSource" AutoGenerateRows="false" Runat="Server">
        <Fields>
            <asp:BoundField DataField="LastName" HeaderText="Last Name:" />
            <asp:BoundField DataField="FirstName" HeaderText="First Name:" />
            <asp:BoundField DataField="Extension" HeaderText="Extension:" />
        </Fields>
</asp:DetailsView>

Now image the DataSource "DetailsSource" return 10 fields in it's SQL and you only want to show 3. Just specify the 3 exact fields you want. So when someone updates the stored proc to return 12 fields your grid is still the same as when you develope it. (Unless someone changes the proc and no longer returns the required fields.)

In regard to your second question, to query the data before it is bound you can put your code in the DetailsView.OnItemDataBound event. Then you can easily loop through the recorsd there and do what you like.

The Row object does not have a dictionary so in reply to your original question

[But rather than referring to rows(16), I'd like to be able to refer to Rows("columnName")]

You can't.

Hope I have cleared up everything here :), if not just yell and we can sort it out.
Avatar of gailhl

ASKER

Well...perhaps I'm completely losing my mind.  Or totally unobservant.  But as far as I can tell, there is no OnItemDataBound event in the DetailsView control.

Are we both talking about Visual Studio 2005 and VB?

Thanks
Gail

PS What I am trying to do is color-code the text displayed in a cell depending on the data value.  The orginal example I posted works but this is a project being built and the procs are not final.  The client is still adding and removing fields etc. so the position changes, and I've already had to change the code twice.
Take a look here....

http://www.thescripts.com/forum/thread424945.html

It is the DataBound event and not ItemDataBound

Basically

void DetailsView1_DataBound(object sender, EventArgs e)
{
          if(((DetailsView)sender).CurrentMode== DetailsViewMode.Edit)
          {
                DropDownList ddl=(DropDownList)((DetailsView)sender).FindContro l("DropDownList1");
                if (ddl1 !=null) //you found the dropdownlist
                {
                    //execute statements to add the desired data to it
                 }
          }
}

This example is in C# and for aa DropDown but it should get you going

This is what the online C# --> VB.Net generator gave me. It is normally accurate but sometimes get's it wrong

    Private Sub DetailsView1_DataBound(ByVal sender As Object, ByVal e As EventArgs)
        If (CType(sender,DetailsView).CurrentMode = DetailsViewMode.Edit) Then
            Dim ddl As DropDownList = CType(CType(sender,DetailsView).FindContro,DropDownList)
            l("DropDownList1")
            If (Not (ddl1) Is Nothing) Then
                'execute statements to add the desired data to it
            End If
        End If
    End Sub

http://carlosag.net/Tools/CodeTranslator/Default.aspx
Okay I posted an attempted answer to two different questions here :)...

Please ignore the DetailsViewMode.Edit part because that does not apply to you, you can cast your label using the findcontrol option and then change it as you like (Change DropDown to label)

Other than that it should work with no problems.
Avatar of gailhl

ASKER

Sorry, it just doesn't work.  The field I'm trying to access in the condition isn't a template field;  it's an asp:checkbox which is databound.

This works - but I don't like the reference by index.

            Dim lblPN As Label = Me.personDetails.FindControl("lblPersonNotes")
            If Not (lblPN Is Nothing) Then
                Dim ckb As CheckBox = Me.personDetails.Rows(16).Cells(1).Controls(0)
                If ckb.Checked = True Then
                    lblPN.ForeColor = Drawing.Color.Red
                Else
                    lblPN.ForeColor = Drawing.Color.Black
                End If
            End If

Perhaps FindControl would work if I change it to a template field -- but I still find it impossible to believe that there is no straightforward way to address the value of an asp databound control without referring to it by index or converting it to a template field.  
Thanks
GHL
ASKER CERTIFIED SOLUTION
Avatar of GavinMannion
GavinMannion

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial