2
votes

asp: le filtre gridview utilisant la zone de liste ne peut pas effectuer de sélection multiple

J'ai cette asp: gridview dans laquelle je montre des données en utilisant la procédure stockée mySql. J'ai cette liste nommée ddlstatus que j'utilise pour filtrer les données. J'utilise viewstate pour afficher les données sélectionnées dans la zone de liste. Le problème est que je veux faire une sélection multiple sur cette listbox et afficher les données pour chaque sélection effectuée dessus, mais quand elle n'affiche que les données de la sélection initiale.

Voici le code côté client:

CREATE DEFINER=`root`@`localhost` PROCEDURE `GetTMData`(in statusVal varchar(45))
BEGIN
SELECT *
   FROM approved
   WHERE (statusVal IS NULL
                OR status = statusVal)
         order by date desc;
END

Voici le code côté serveur:

private void BindDropDownList()
{
    PopulateDropDown(ddlstatus, lblstat.Text);
}
private void PopulateDropDown(ListBox ddl, string columnName)
{
    ddl.Items.Clear();
    ddl.DataSource = BindDropDown(columnName);
    ddl.DataTextField = columnName;
    ddl.DataValueField = columnName;
    ddl.DataBind();
    ddl.Items.Insert(0, new ListItem("Please select", "0"));
}
private void BindGrid()
{
    DataTable dt = new DataTable();
    String strConnString = System.Configuration.ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
    MySqlConnection con = new MySqlConnection(strConnString);
    MySqlDataAdapter sda = new MySqlDataAdapter();
    MySqlCommand cmd = new MySqlCommand("GetTMData");
    cmd.CommandType = CommandType.StoredProcedure;  
    string statusVal = null;
    if (ViewState["stat"] != null && ViewState["stat"].ToString() != "0")
    {
        statusVal = ViewState["stat"].ToString();
    }
    cmd.Parameters.AddWithValue("statusVal", statusVal);
    cmd.Connection = con;
    sda.SelectCommand = cmd;
    sda.Fill(dt);
    gdvTM.DataSource = dt;
    int i = dt.Rows.Count;
    gdvTM.DataBind();
    this.BindDropDownList();
    TableCell cell = gdvTM.HeaderRow.Cells[0];
    setDropdownselectedItem(ViewState["stat"] != null ? (string)ViewState["stat"] : string.Empty, ddlstatus);
}
private void setDropdownselectedItem(string selectedvalue, ListBox ddl)
{
    if (!string.IsNullOrEmpty(selectedvalue))
    {
         ddl.Items.FindByValue(selectedvalue).Selected = true;

    }
}
protected void DropDownChange(object sender, EventArgs e)
 {
      ListBox dropdown = (ListBox)sender;
      string selectedValue = dropdown.SelectedItem.Value;
      switch (dropdown.ID.ToLower())
      {
          case "ddlstatus":
             ViewState["stat"] = selectedValue;
             break;
      }

      this.BindGrid();
 }

private DataTable BindDropDown(string columnName)
{
    string username = uName.Text;
    String strConnString = System.Configuration.ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
    MySqlConnection con = new MySqlConnection(strConnString);
    MySqlCommand cmd = new MySqlCommand("SELECT DISTINCT (" + columnName + ") FROM approved WHERE tm = @tm AND " + columnName + " IS NOT NULL", con);
    MySqlDataAdapter sda = new MySqlDataAdapter(cmd);
    cmd.Parameters.AddWithValue("@tm", username);
    DataTable dt = new DataTable();
    sda.Fill(dt);
    return dt;
}

Voici la procédure stockée MySql:

<asp:Label ID="lblstat" Text="status" Visible="false" runat="server"></asp:Label>
<asp:ListBox ID="ddlstatus" runat="server" OnSelectedIndexChanged="DropDownChange" AutoPostBack="true" AppendDataBoundItems="true" SelectionMode="Multiple"></asp:ListBox>

<asp:GridView ID="gdvTM" runat="server" ControlStyle-Width="100%"  AutoGenerateColumns="False" DataKeyNames="ID" OnRowDeleting="gdvTM_RowDeleting" PageSize="5" CssClass="cssgridview" AlternatingRowStyle-BackColor="#d5d8dc">
    <Columns >
       <asp:TemplateField HeaderText="Current Status">
         <ItemTemplate >
             <asp:Label ID="lblcstat" runat="server" Text='<%# Eval("status") %>'></asp:Label>
        </ItemTemplate>
      </asp:TemplateField>
    </Columns>
</asp:GridView>


8 commentaires

cela signifie que si vous choisissez quatre éléments dans la zone de liste, vous ne recevez que la première valeur de l'élément sur la ligne string selectedValue = dropdown.SelectedItem.Value; dans le gestionnaire d'événements DropDownChange , n'est-ce pas? puis chargement des données pour cet élément uniquement


@ er-sho oui et aussi après la publication, les trois autres éléments ne sont pas sélectionnés dans la liste


savez-vous comment passer plusieurs valeurs à un seul paramètre dans une procédure stockée, par exemple si je sélectionne a , b , c alors celles-ci seront transmises dans votre SP avec le paramètre statusVal ?


@ er-sho ouais nous devons utiliser IN, non? mais pouvons-nous le faire en utilisant foreach (ListItem Item1 in ddlstatus.items) {} à la place?


Alors, comment est le besoin d'entrée pour ce paramètre statusVal ? signifie son tableau comme ["a", "b", "c"] ou seulement une chaîne comme a, b, c ?


@ er-sho chaîne normale uniquement


@ er-sho ok bro :)


Montrez-nous le SQL généré; Je pense que cela rendra le problème évident.


3 Réponses :


2
votes

Tout d'abord, la publication automatique ne vous permet pas de sélectionner plusieurs éléments car jusqu'à ce que le deuxième élément soit sélectionné, la publication se produit déjà par le premier élément sélectionné,

Vous devez définir AutoPostBack = "false" code> pour votre zone de liste,

CREATE DEFINER=`root`@`localhost` PROCEDURE `GetTMData1`(in statusVal varchar(255))
BEGIN

IF statusVal = '\'\'' THEN 
   select * from approved;
ELSE
  SET @sql = CONCAT('SELECT * FROM approved WHERE status IN (', statusVal, ')');
  PREPARE stmt FROM @sql;
  EXECUTE stmt;
  DEALLOCATE PREPARE stmt;    
END IF ;        
END

Pour collecter plusieurs éléments sélectionnés, nous choisissons simplement le bouton par exemple, vous pouvez collecter ces éléments où vous voulez,

Ensuite, ajoutez un bouton qui appellera le code ci-dessous

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        //Populate your list box here
    }
}

Sur le gestionnaire d'événements du bouton ci-dessus, ajoutez le code ci-dessous,

string statusVal = null;
if (ViewState["stat"] != null && ViewState["stat"].ToString() != "0")
{
    statusVal = ViewState["stat"].ToString();
}
cmd.Parameters.AddWithValue("statusVal", statusVal);  //<= Now this string variable contains comma separated list box items values.

Puis le les éléments séparés par des virgules dans votre ViewState seront utilisés dans votre paramètre de procédure stockée

protected void button1_Click(object sender, EventArgs e)
{
    var selectedNames = ddlstatus.Items.Cast<ListItem>()
                         .Where(i => i.Selected)
                         .Select(i => i.Value)
                         .ToList();

    string selectedValue = string.Join("','", selectedNames);

    selectedValue = "'" + selectedValue + "'";

    ViewState["stat"] = selectedValue;
}

Si vous remplissez votre zone de liste sur Page Load code > puis assurez-vous de le remplir dans ! Page.IsPostBack comme

<asp:Button ID="button1" runat="server" OnClick="button1_Click" Text="Click"/>

Et votre SP est

<asp:ListBox ID="ddlstatus" runat="server" AutoPostBack="false" AppendDataBoundItems="true" SelectionMode="Multiple"></asp:ListBox>


14 commentaires

Avez-vous reçu plusieurs valeurs en cliquant sur le bouton? Ajouter un point d'arrêt sur la ligne => var selectedNames ..


J'obtiens l'erreur "La référence d'objet n'est pas définie sur une instance d'un objet."


Erreur Sur quelle ligne?


continuons cette discussion dans le chat .


Le tableau de chaînes passe-t-il au paramètre SP?


Hé frère, pouvons-nous nous connecter à ce sujet aujourd'hui?


@prkash, Oh votre commentaire n'apparaît pas dans ma notification donc je n'ai pas remarqué. Et oui, nous pouvons nous connecter demain, mais certaines personnes refusent ma réponse. Je vais donc le supprimer une fois votre problème résolu.


Lors de l'application du SP ci-dessus pour le filtrage de plusieurs listes déroulantes, je devrai créer autant de combinaisons pour que cela fonctionne, je dois encore trouver un moyen d'obtenir la même chose pour plusieurs listes déroulantes


Oui, je pense que le nombre de combinaisons est indispensable, mais SP fonctionne-t-il pour plusieurs combinaisons?


Je pense que si vous postez sur SO, vous obtiendrez probablement une meilleure réponse de la part des gars de my-sql. parce que son SP compliqué à écrire pour nous. Tout expert vous donnera une meilleure solution


Si vous prévoyez de publier sur SO, mentionnez ce que nous avons fait hier avec SP avec un seul paramètre et que vous souhaitez faire de même avec plusieurs paramètres.


ok bro, j'essaye quelque chose de différent maintenant, au lieu d'utiliser SP, j'écris la requête sur le code. Je vais vous mettre à jour comment ça se passe


Bro cette méthode semble fonctionner, mais il y a un problème mineur, pouvons-nous nous connecter?


stackoverflow.com/questions/55569672/...



3
votes

Veuillez créer une listbox multiple

     Message.Text = "You chose: <br />";

     // Iterate through the Items collection of the ListBox and 
     // display the selected items.
     foreach (ListItem item in ListBox1.Items)
     {

        if(item.Selected)
        {

           Message.Text += item.Text + "<br />";

        }

     }

  }

Puis côté serveur void SubmitBtn_Click (Expéditeur de l'objet, EventArgs e) {

<asp:ListBox id="ListBox1" 
           Rows="6"
           Width="100px"
           **SelectionMode="Multiple"** 
           runat="server">

         <asp:ListItem Selected="True">Item 1</asp:ListItem>
         <asp:ListItem>Item 2</asp:ListItem>
         <asp:ListItem>Item 3</asp:ListItem>
         <asp:ListItem>Item 4</asp:ListItem>
         <asp:ListItem>Item 5</asp:ListItem>
         <asp:ListItem>Item 6</asp:ListItem>

      </asp:ListBox>


0 commentaires

1
votes

Il y a quelques problèmes que j'ai pu repérer et qui devront peut-être être résolus,

  1. Assurez-vous que la méthode BindDropDownList n'est appelée que sur une publication non (actualisation de la page), car votre méthode PopulateDropDown efface les éléments de la liste, ce qui signifie cet état d'affichage ne peut pas être restauré dans une publication, d'où la raison probable pour laquelle un seul élément est sélectionné.

  2. Je ne suis pas à 100% du schéma de la table, mais le SQL fourni ne semble pas pouvoir interroger correctement par plus d'un état, vous devriez probablement envoyer une liste de valeurs séparées par des virgules, et en SQL transformez-les en une table temporaire afin de rechercher efficacement les éléments avec plusieurs statuts (vous devriez probablement créer une nouvelle question pour cela).

  3. N'utilisez pas SelectedItem pour les sélections multiples, vous devez à la place itérer vos éléments de liste pour ceux qui sont sélectionnés, et vous n'avez pas besoin d'utiliser ViewState code > pour le transmettre (vous l'avez probablement fait à cause du point 1 ci-dessus). Par exemple, vous pouvez remplacer votre méthode BindGrid et DropDownChange par:

private void BindGrid()
{
    DataTable dt = new DataTable();
    String strConnString = System.Configuration.ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
    MySqlConnection con = new MySqlConnection(strConnString);
    MySqlDataAdapter sda = new MySqlDataAdapter();
    MySqlCommand cmd = new MySqlCommand("GetTMData");
    cmd.CommandType = CommandType.StoredProcedure;  
    string statusVal = null;
     foreach (ListItem item in ddlstatus.Items)
     {
        if(item.Selected)
        {
           if(statusVal.length > 0)
               statusVal += ",";
           statusVal += item.Value;
        }
     }
    cmd.Parameters.AddWithValue("statusVal", statusVal);
    cmd.Connection = con;
    sda.SelectCommand = cmd;
    sda.Fill(dt);
    gdvTM.DataSource = dt;
    gdvTM.DataBind();

}

protected void DropDownChange(object sender, EventArgs e)
 {
      this.BindGrid();
 }


2 commentaires

désolé, vous avez raison, j'espérais que ma réponse clarifierait le vote défavorable. En gros, vous n'avez pas besoin de changer l'interface utilisateur (ajouter un bouton, et désactiver l'autopostback sur la liste) si le problème principal réel est résolu, la liste déroulante étant rebondie sur une publication (1.) et que sur votre réponse vous avez gardé l'utilisation de viewstate pour passer la valeur de statut est également une surcharge inutile (et la taille de viewstate) et vous n'avez pas réussi à résoudre le problème avec la procédure (2.) car c'est mysql Je n'ai pas de réponse spécifique, mais je suis sûr que quelqu'un sinon.


J'ai donné une solution comme sur ma réponse au problème d'OP après avoir analysé le code source complet via un accès à distance via TeamViewer. L'état de vue est obligatoire pour lui. Je pense que vous devriez annuler ma réponse. Parce que vous donneriez une solution basée sur une approche primaire et directe sans connaître le code source complet d'OP. :)