0

I have a bit of a difficult problem which I can't seem to find out how to solve.

Basically, I have a couple tables on my database which, identify, by client, which divs IDs the client has access to, by using the tab

So I have a table which identifies the divs by their ID, by using the table index:

id | id_div
0 | D0
1 | D1 (and so on..)

And then another one which has only the clients ID and the divs (identified by the "id" field) he has access to:

client_id | div_id 29 | 0 29 | 1 (and so on..)

Then I'm cross referencing which divs should be visible and which should not. The problem is I am getting the divs id as a string and in order to be able to tell in code-behind to set the visibility to false I need to reference the div in itself..

A sample:

<dx:TabPage Name="tabServico" Text="<%$ Resources:InterfaceGenerica, lblServico %>">
    <ContentCollection>
        <dx:ContentControl>
           <div class="conteudo_pagina_tab">
               <asp:HiddenField ID="hidID" runat="server" Value="0" EnableViewState="true" />
               <asp:HiddenField ID="hidIdCliente" runat="server" Value="0" EnableViewState="true"/>
               <div id="D0" runat="server">
                   <div class="cols coluna1">
                       <asp:Literal ID="litClientes" runat="server" Text="<%$ Resources:InterfaceGenerica, lblCliente %>"></asp:Literal>
                    </div>
                    <div class="cols coluna2-4">
                        <dx:ASPxComboBox ID="cboClientes" runat="server" HelpText="" ValueField="id_cliente" TextField="nome_completo" SelectedValue="" Width="100%" AutoPostBack="true"></dx:ASPxComboBox>
                     </div>
                </div>
                <clear></clear>
                <div id="D1" runat="server">
                     <div class="cols coluna1">
                        <asp:Literal ID="litTipoOperacao" runat="server" Text="<%$ Resources:InterfaceGenerica, lblOperacao %>"></asp:Literal>
                     </div>
                     <div class="cols coluna2-4">
                         <dx:ASPxComboBox ID="cboTipoOperacao" runat="server" Width="100%" HelpText="" ValueField="id_operacoes" TextField="nome" SelectedValue="" AutoPostBack="true">
                          </dx:ASPxComboBox>
                     </div>
                 </div>
                 <clear></clear>
                 <div id="D2" runat="server">
                     <div class="cols coluna1">
                        <asp:Literal ID="litTipoServs" runat="server" Text="<%$ Resources:InterfaceGenerica, lblTipoServico %>"></asp:Literal>
                      </div>
                 <div class="cols coluna2-4">
                     <dx:ASPxComboBox ID="cboTipoServs" runat="server" HelpText="" ValueField="id_tipo_servs" TextField="nome" SelectedValue="" AutoPostBack="true" Width="100%"></dx:ASPxComboBox>
                 </div>
             </div>
             <div id="D3" runat="server">
                   <div class="cols coluna5">
                       <asp:Literal ID="litSubTipoServs" runat="server" Text="<%$ Resources:InterfaceGenerica, lblSubtipoServico %>"></asp:Literal>
                   </div>
                   <div class="cols coluna6-8">
                       <dx:ASPxComboBox ID="cboSubTipoServs" runat="server" HelpText="" ValueField="id_tipo_subtipos" TextField="nome" SelectedValue=""></dx:ASPxComboBox>
                    </div>
               </div>

And in code behind I have:

Dim cross As New Hashtable()
    Dim divsCliente() As String

    Dim lstDivs As List(Of campos_agd_form)
    lstDivs = campos_agd_form_mapper.CarregarDivs()

    If lstDivs IsNot Nothing Then
        For Each i In lstDivs
            cross.Add(i.id, i.id_div)
        Next
    End If

    Dim lstDivsCliente As List(Of clientes_campos_agd)
    lstDivsCliente = clientes_campos_agd_mapper.CarregarCamposCliente(guser.id)

    If lstDivsCliente IsNot Nothing Then
        divsCliente = (lstDivsCliente.Item(0).id_campos_enum).Split(",")
    End If
    'Dim divsCliente() As Integer = Convert.ToInt32((lstDivsCliente.id_divs).Split(","))

    For Each item In cross
        For Each i In divsCliente
            If item.Key = Convert.ToInt32(i) Then
                Dim div As System.Web.UI.HtmlControls.HtmlGenericControl
                div = TryCast(item.Value, System.Web.UI.HtmlControls.HtmlGenericControl)
                div.Visible = False
            End If
        Next
    Next

As I was already expecting I can't convert a string into a HtmlObject so what I need to do is to find an object by it's id (the string), without having to go through the parent-object (basically, search the whole document, like one would do with javascript with a getElementById)

How can this be accomplished?

The framework I'm using is .NET 4.0

2
  • Have you tried adding a parent div (which is runat="server") for your divs and use it to to find the div with specific id? IE. parentDiv.FindControl("D0")? Commented Nov 7, 2013 at 13:50
  • That would require me to add a parent div to the whole page I believe.. I've updated my aspx code with a more complete sample, instead of just one div.. Commented Nov 7, 2013 at 15:00

2 Answers 2

1

I Recommend the following approach.

You need to know which information to show to each user, so you might want to store this in session for example (Global.asax):

Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
    ' Fetch from DB
    Session("Rights") = {"MyID1", "MyID3"}
End Sub

Then create a base user control that checks from the session if it's id is in the list of the rights the user has. If not, the control will automatically hide it self:

Imports System.Linq

Public MustInherit Class MyBaseControl
    Inherits System.Web.UI.UserControl

    Private Sub Page_Init(sender As Object, e As System.EventArgs) Handles Me.Init
        If Page.IsPostBack Then Return

        Dim rights As String() = CType(Session("Rights"), String())
        If Not rights.Any((Function(s) s = Me.ID)) Then Me.Visible = False
    End Sub
End Class

Then create x number of content controls that inherit from this base control. These controls can have totally different content, but consider making as few as possible, since your D0, D1 etc seem to have almost same content. So just customize the control to handle different texts and values:

Public Class MyControl1
    Inherits MyBaseControl
End Class

Then on the page you will have as many of these controls as needed:

<div>
    <uc1:MyControl1 ID="MyID1" runat="server" />
    <uc2:MyControl2 ID="MyID2" runat="server" />
    <uc3:MyControl3 ID="MyID3" runat="server" />
</div>

Hope this helps.

Sign up to request clarification or add additional context in comments.

1 Comment

That seems like a possible approach but I ended up using another approach which I'll post in a moment
1

So, I ended up doing things a little differently.

Basically I'm using a ClientScriptManager, and constructing an array with the elements to hide. (Which is then passed to the client side).

So the function now looks like this:

Private Sub ManipulaFormCliente()
    Dim cross As New Hashtable()
    Dim divsCliente() As String = New String() {}
    Dim aux() As String = New String() {}
    Dim cs As ClientScriptManager = Page.ClientScript

    Dim lstDivs As List(Of campos_agd_form)
    lstDivs = campos_agd_form_mapper.CarregarDivs()

    If lstDivs IsNot Nothing Then
        For Each i In lstDivs
            cross.Add(i.id, i.id_div)
        Next
    End If

    Dim lstDivsCliente As List(Of clientes_campos_agd)
    lstDivsCliente = clientes_campos_agd_mapper.CarregarCamposCliente(" id_cliente = " & Convert.ToInt32(hidIdCliente.Value))

    If lstDivsCliente IsNot Nothing Then
        If lstDivsCliente.Count <> 0 Then
            divsCliente = (lstDivsCliente.Item(0).id_campos_enum).Split(",")
        End If
    End If

    For Each item In cross
        For Each i In divsCliente
            If item.Key = Convert.ToInt32(i) Then
                cs.RegisterArrayDeclaration("divsCliente", "'" & item.Value & "'")
            End If
        Next
    Next
End Sub

Then, on the client side I made a function which runs once the window has loaded, and uses the array constructed on code-behind to apply a css "display: none" on the divs whose IDs get passed on the array.

The code is the following:

window.onload = function hideFields() {
        if (divsCliente.length > 0) {
            for (var i = 0; i < divsCliente.length; i++) {
                document.getElementById(divsCliente[i]).style.display = 'none';
            }
        }
    }

This implements the behaviour desired: Whenever there's a postback (and respective load) this function is run, hiding the required divs/fields.

As a final touch, I had to add the 'clientidmode = "static"' attribute to the divs, in order to get the getElementById() function to work properly (according to the data in the DB)

I hope this helps anyone in need of a similar solution.

2 Comments

That works if javascript is enabled. But keep in mind you are generating alot of excess html that is not needed. If the html is not needed, you should not generate it in the first place. Also the user can easily modify the fields because they are in the html (only hidden) so it might generate security issue. If indeed the user should not be able to modify these fields, they should not be in the html.
I'm perfectly aware of that scenario. But the extra divs are indeed necessary (since I don't want the controls to disappear) and the users in this app (very specific intranet thingy) are generally too dumb in tech matters, so this solution works OK, although it is not ideal

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.