Reputation: 1
I'm trying to make limitation in listbox so that user only can pick 5 item in listbox. Currently I got to remove last selected item in the listbox, but in the hiddenfield its not updated.
listbox name = ddl_tags hiddenfield name = ddl_tags_selected
eg: user choose : item1, item2, item3, item4, item5, item 6 after they select item6, that index of item6 is remove but in the hiddenfield it still contain the item 6.
protected void ddl_tag_SelectedIndexChanged(object sender, EventArgs e)
{
int count = 0;
int limit = 0;
string lastSelectedIndex;
string tagSelected = ddl_tags_selected.Value;
tagSelected = string.Join(",", tagSelected.Split(',').Select(x => string.Format("{0}", x)).ToList());
for (int i = 0; i < ddl_tags.Items.Count; i++)
{
if (ddl_tags.Items[i].Selected)
{
if (ViewState["CountLimit"] != null)
{
count++;
ViewState["CountLimit"] = count;
limit = (int)ViewState["CountLimit"];
}
else
{
count++;
ViewState["CountLimit"] = count;
}
if (limit > 5)
{
ScriptManager.RegisterStartupScript(this, this.GetType(), "alert", "Swal.fire({position: 'center',type: 'error',title: 'Only 5 tags are allowed.',showConfirmButton: false,timer: 2750});", true);
//Get the last selected items when the items selected exceeds in 5
lastSelectedIndex = tagSelected;
//Unselect the 6th items selected
ddl_tags.Items[5].Selected = false;
}
}
}
}
`
<div class="form-group col-md-4" id="tagsDiv" runat="server"visible="false"><label for="Tags">Tags :</label>
<asp:ListBox ID="ddl_tags" runat="server" class="form-control" SelectionMode="Multiple" CssClass="pm form-control select2" Width="100%" Height="100%" AutoPostBack="true" OnSelectedIndexChanged="ddl_tag_SelectedIndexChanged"></asp:ListBox>
<asp:HiddenField ID="ddl_tags_selected" runat="server" />
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" InitialValue="" runat="server" Style="color: red;" ControlToValidate="ddl_tags" ErrorMessage="This field is required" ToolTip="This field is required" ValidationGroup="DeviationValidate"></asp:RequiredFieldValidator></div>
`
Upvotes: 0
Views: 147
Reputation: 49159
You actually don't need a hidden field.
There is a "count" of the items, and there is a selected array. HOWEVER these collections are SORTED by id order, and as a result, you can't know what the last item selected was.
You could for example do this:
<h2>Please select up to 5 cities</h2>
<asp:ListBox ID="ListBox1" runat="server"
DataValueField="ID"
DataTextField="City" OnSelectedIndexChanged="ListBox1_SelectedIndexChanged"
Width="260px" Height="330px"
SelectionMode="Multiple" AutoPostBack="true" >
</asp:ListBox>
And then just build a list of items, say like this:
List<int> MyIDList = new List<int>();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
LoadList();
ViewState["MyIDList"] = MyIDList;
}
MyIDList = ViewState["MyIDList"] as List<int>;
}
void LoadList()
{
DataTable rstData = MyRst("SELECT ID, City FROM City ORDER BY City");
ListBox1.DataSource = rstData;
ListBox1.DataBind();
}
protected void ListBox1_SelectedIndexChanged(object sender, EventArgs e)
{
// add any selected (using index ref) to list
int i = 0;
for (i=0;i < ListBox1.Items.Count;i++) {
if (ListBox1.Items[i].Selected)
{
if (!MyIDList.Contains(i))
MyIDList.Add(i);
}
else
if (MyIDList.Count > 0)
if (MyIDList.Contains(i))
MyIDList.Remove(i);
}
// check for count > 5
if (MyIDList.Count > 5)
{
int r = MyIDList[MyIDList.Count - 1];
ListBox1.Items[r].Selected = false;
MyIDList.RemoveAt(MyIDList.Count - 1);
}
}
public DataTable MyRst(string strSQL)
{
var rst = new DataTable();
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
{
cmdSQL.Connection.Open();
// fill items table
rst.Load(cmdSQL.ExecuteReader());
}
}
return rst;
}
So, if > 5, then we un-select the last one.
To be fair, I would try and write this code 100% client side.
Upvotes: 0