I don't know if I am allowed to post such a specific issue here.
The scenario is that I have a Product that has a many to many relationship with Category.
Means one product may belong to multiple categories and a category may have multiple products. Now on the form I have provide a dropdown along with a button that says add another category and when I click on that button another dropdown should appear below that first dropdown. and the selected item of the previous dropdown must be remove from the dropdown items.
Below is my code of the dropdown's repeater and the two buttons mentioned.
protected void btnAddAnotherCategory_Click(object sender, EventArgs e)
{
List<int> selectedIndices = new List<int>();
foreach (RepeaterItem item in rptCategories.Items)
{
if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
{
DropDownList ddlCategory = (DropDownList)item.FindControl("ddlCategory");
int selectedIndex = ddlCategory.SelectedIndex;
selectedIndices.Add(selectedIndex);
}
}
ViewState["objSelectedIndices"] = selectedIndices;
rptCategories_DataSource("add", false);
}
protected void btnRemoveCategory_Click(object sender, EventArgs e)
{
List<int> selectedIndices = new List<int>();
foreach (RepeaterItem item in rptCategories.Items)
{
if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
{
DropDownList ddlCategory = (DropDownList)item.FindControl("ddlCategory");
int selectedIndex = ddlCategory.SelectedIndex;
selectedIndices.Add(selectedIndex);
}
}
ViewState["objSelectedIndices"] = selectedIndices;
rptCategories_DataSource("remove", false);
}
protected void rptCategories_DataSource(string editCommand, bool pageLoad)
{
switch (editCommand)
{
case "add":
if (ViewState["categoriesCount"] == null)
{
List<Category> count = new List<Category>();
count.Add(new Category());
ViewState["categoriesCount"] = count;
}
if (!pageLoad)
{
List<Category> count = (List<Category>)ViewState["categoriesCount"];
count.Add(new Category());
ViewState["categoriesCount"] = count;
}
List<Category> objCategories = (List<Category>)ViewState["categoriesCount"];
objCategories = objCategories.Where(x => x.StatusID != 3).ToList();
rptCategories.DataSource = objCategories;
rptCategories.DataBind();
break;
case "remove":
if (((List<Category>)ViewState["categoriesCount"]).Count > 1)
{
List<Category> count = (List<Category>)ViewState["categoriesCount"];
count.Remove(count.Last());
count = count.Where(x => x.StatusID != 3).ToList();
ViewState["categoriesCount"] = count;
rptCategories.DataSource = count;
rptCategories.DataBind();
}
break;
}
}
protected void rptCategories_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
Category objCategory = (Category)e.Item.DataItem;
DropDownList ddlCategory = (DropDownList)e.Item.FindControl("ddlCategory");
ddlCategory.DataSource = new CategoryBLL().GetAllCategoriesWithStatus();
ddlCategory.DataTextField = "Name";
ddlCategory.DataValueField = "ID";
ddlCategory.DataBind();
if (objCategory.CategoryID != null)
ddlCategory.SelectedValue = objCategory.CategoryID.ToString();
if (ViewState["objSelectedIndices"] != null)
{
List<int> objSelectedIndices = (List<int>)ViewState["objSelectedIndices"];
if (objSelectedIndices.Count > e.Item.ItemIndex)
ddlCategory.SelectedIndex = objSelectedIndices.ElementAt(e.Item.ItemIndex);
}
if (e.Item.ItemIndex < ((List<Category>)rptCategories.DataSource).Count - 1)
{
ddlCategory.Enabled = false;
}
btnAddAnotherCategory.Visible = true;
btnRemoveCategory.Visible = true;
if (rptCategories.Items.Count < 1)
{
btnRemoveCategory.Visible = false;
}
if (rptCategories.Items.Count >= new CategoryBLL().GetAllCategoriesWithStatus().Count - 1)
{
btnAddAnotherCategory.Visible = false;
}
}
The StatusID mentioned in the code is to determine the deleted products as I am not ACTUALLY deleting the Product rather only setting its StatusID
Now the problem is that my code works fine with the above statements but as you can see it does not remove the selected items from the dropdown. The dropdown's are required to be populated from a single table everytime. The tricky part is removing the selecteditems in the previous repeateritems dropdownlist.
Any solution would be welcomed.
Related
I am trying to implement a multiple items select in multiple listboxes. Is this possible?
Requirements:
When user selects an item in ListBox1 - items in ListBox2 and ListBox3 should be selected.
When user deselects and item in ListBox1 - Items in ListBox2 and ListBox2 should be deselected.
I am able to achieve this on LB1.
Same behavior 1 and 2 should repeat for ListBox2 and ListBox3.
I am having difficulty here.
I have the code below - but of course it runs into stackoverflow exception. What am I missing?
private void listBox_1_SelectedIndexChanged_(object sender, EventArgs e)
{
int userSelectedIndex = listBox_1.Items.Count;
if (listBox_1.SelectedIndices.Count > 0)
{
for (int count = 0; count < listBox_1.Items.Count; count++)
{
// Determine if the item is selected.
if (listBox_1.GetSelected(count) == true)
{
if (count <= listBox_2.Items.Count)
listBox_2.SetSelected(count, true);
if (count <= listBox_3.Items.Count)
listBox_3.SetSelected(count, true);
}
else if (listBox_1.GetSelected(count) == false)
{
// Select all items that are not selected.
if (count <= listBox_2.Items.Count)
listBox_2.SetSelected(count, false);
if (count <= listBox_3.Items.Count)
listBox_3.SetSelected(count, false);
}
}
}
}
private void listBox_2_SelectedIndexChanged(object sender, EventArgs e)
{
int userSelectedIndex = listBox_2.Items.Count;
if (listBox_2.SelectedIndices.Count > 0)
{
for (int count = 0; count < listBox_2.Items.Count; count++)
{
// Determine if the item is selected.
if (listBox_2.GetSelected(count) == true)
{
if (count <= listBox_1.Items.Count)
listBox_1.SetSelected(count, true);
if (count <= listBox_3.Items.Count)
listBox_3.SetSelected(count, true);
}
else if (listBox_2.GetSelected(count) == false)
{
// Select all items that are not selected.
if (count <= listBox_1.Items.Count)
listBox_1.SetSelected(count, false);
if (count <= listBox_3.Items.Count)
listBox_3.SetSelected(count, false);
}
}
}
}
This field is used to avoid Stack Overflow Exceptions.
private bool _isUpdating;
I am also using the SelectedValueChanged event instead of SelectedIndexChanged but it should still work, here is the 3 different checkboxes (this could be improved by refactoring how it handles which listbox to update)
private void listBox1_SelectedValueChanged(object sender, EventArgs e)
{
if (this._isUpdating)
{
//// Prevent Stack Overflow by exiting out
return;
}
var selectedIndexes = this.listBox1.SelectedIndices;
this._isUpdating = true;
this.listBox2.SelectedItems.Clear();
this.listBox3.SelectedItems.Clear();
foreach (int index in selectedIndexes)
{
//// Listbox2
var foundItem = this.listBox2.Items[index];
this.listBox2.SelectedItems.Add(foundItem);
//// Listbox3
var foundItem2 = this.listBox3.Items[index];
this.listBox3.SelectedItems.Add(foundItem2);
}
this._isUpdating = false;
}
private void listBox2_SelectedValueChanged(object sender, EventArgs e)
{
if (this._isUpdating)
{
//// Prevent Stack Overflow by exiting out
return;
}
var selectedIndexes = this.listBox2.SelectedIndices;
this._isUpdating = true;
this.listBox1.SelectedItems.Clear();
this.listBox3.SelectedItems.Clear();
foreach (int index in selectedIndexes)
{
//// Listbox1
var foundItem = this.listBox1.Items[index];
this.listBox1.SelectedItems.Add(foundItem);
//// Listbox3
var foundItem2 = this.listBox3.Items[index];
this.listBox3.SelectedItems.Add(foundItem2);
}
this._isUpdating = false;
}
private void listBox3_SelectedValueChanged(object sender, EventArgs e)
{
if (this._isUpdating)
{
//// Prevent Stack Overflow by exiting out
return;
}
var selectedIndexes = this.listBox3.SelectedIndices;
this._isUpdating = true;
this.listBox1.SelectedItems.Clear();
this.listBox2.SelectedItems.Clear();
foreach (int index in selectedIndexes)
{
//// Listbox1
var foundItem = this.listBox1.Items[index];
this.listBox1.SelectedItems.Add(foundItem);
//// Listbox2
var foundItem2 = this.listBox2.Items[index];
this.listBox2.SelectedItems.Add(foundItem2);
}
this._isUpdating = false;
}
Which as stated previously, avoids the Stack Overflow Exception and ensures that selecting / deselecting an item in the Listbox at a given index will also select the item at the other listboxes index.
This is my code for adding gridview with arrows..Gridview is sorting by ascending and descending but i am unable to add arrows.
protected void grdInformation_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row != null && e.Row.RowType == DataControlRowType.Header)
{
foreach (TableCell cell in e.Row.Cells)
{
if (cell.HasControls())
{
LinkButton button = cell.Controls[0] as LinkButton;
HtmlGenericControl gv = new HtmlGenericControl("div");
Label lnkName = new Label();
lnkName.Text = button.Text;
if (button != null)
{
Image imageSort = new Image();
imageSort.ImageUrl = "~/images/asc.png";
if (grdInformation.SortExpression == button.CommandArgument)
{
if (grdInformation.SortDirection == SortDirection.Ascending)
{
imageSort.ImageUrl = "~/images/desc.png";
}
else
{
imageSort.ImageUrl = "~/images/asc.png";
}
}
gv.Controls.Add(lnkName);
gv.Controls.Add(imageSort);
button.Controls.Add(gv);
}
}
}
}
}
}}
Dono where i am going wrong , I have took an event for sorting , this is my code for sorting gridview it is working finee, but i am unable to add arrows to the girdview , the above i have tried but its not adding me arrows, how do i add arrows ??
i have tried some articles but i am unable to add arrows with ascending and descending , gridview is sorting when clicking on header rows , but need to display to the user that he can sort based on ascending arrows and descending arrows ...
protected void grdInformation_Sorting(object sender, GridViewSortEventArgs e)
{
if (CurrentSortExpression == e.SortExpression.ToString())
{
if (CurrentSortDirection == "asc")
CurrentSortDirection = "desc";
else
CurrentSortDirection = "asc";
}
else
{
CurrentSortExpression = e.SortExpression.ToString();
CurrentSortDirection = "asc";
}
if (e.SortExpression.Trim() == this.SortField)
{
this.sortDirection = (this.sortDirection == "DESC" ? "ASC" : "DESC");
}
else
{
this.sortDirection = "ASC";
}
ViewState["SortDirection"] = this.sortDirection;
this.SortField = e.SortExpression;
Bindinfo(GetInformation(ddlStatus.SelectedValue, ddlGroups.SelectedValue));
}
Please help ??
You can add the images like this.
System.Web.UI.WebControls.Image sortArrow = new System.Web.UI.WebControls.Image();
private void addSortImages()
{
int columnIndex = 0;
//set the image url
sortArrow.ImageUrl = "~/images/asc.png";
if (mySortDirection == SortDirection.Descending)
{
sortArrow.ImageUrl = "~/images/desc.png";
}
//check for rows in the gridview
if (GridView1.Rows.Count > 0)
{
//loop all the columns
foreach (DataControlFieldHeaderCell cell in GridView1.HeaderRow.Cells)
{
if (cell.ContainingField.SortExpression == mySortExpression)
{
columnIndex = GridView1.HeaderRow.Cells.GetCellIndex(cell);
}
}
//add the image to the correct header cell
GridView1.HeaderRow.Cells[columnIndex].Controls.Add(sortArrow);
}
}
I have a gridview and it will maintain checkboxes state while paging in gridview.why the checkboxes will still maintain when i refresh the page?how to disable the checkboxes state maintain after i refresh the page or submit data to database?
private void savechkdvls()
{
ArrayList usercontent = new ArrayList();
int index = -1;
foreach (GridViewRow gvrow in GrdRole.Rows)
{
index = Convert.ToInt32(GrdRole.DataKeys[gvrow.RowIndex].Value);
bool result = ((CheckBox)gvrow.FindControl("chkSelect")).Checked;
if (Session["chkditems"] != null)
usercontent = (ArrayList)Session["chkditems"];
if (result)
{
if (!usercontent.Contains(index))
usercontent.Add(index);
}
else
usercontent.Remove(index);
}
if (usercontent != null && usercontent.Count > 0)
Session["chkditems"] = usercontent;
}
private void chkdvaluesp()
{
ArrayList usercontent = (ArrayList)Session["chkditems"];
if (usercontent != null && usercontent.Count > 0)
{
foreach (GridViewRow gvrow in GrdRole.Rows)
{
int index = Convert.ToInt32(GrdRole.DataKeys[gvrow.RowIndex].Value);
if (usercontent.Contains(index))
{
CheckBox myCheckBox = (CheckBox)gvrow.FindControl("chkSelect");
myCheckBox.Checked = true;
}
}
}
}
if (!IsPostBack)
{
filldropdown();
Bind();
}
You're able to use
ViewState.Clear();
Response.Redirect("~/PageXXX.aspx");
to clear the ViewState
I am really confused on thinking which control to use for my purpose.
I am having list of items say item1 to item10. User can select 4 or 5 items in any order.
Now user selected items has to be separated in same order.
For example, if the user selected the items in following order, item4, item8, item3 and item2.
I want it in the same order. item4,item8,item3,item2.
How do I achieve this in winforms control?
It is not a very nice solution but I wrote it as you asked.
Set the SelectionMode of your ListBox to MultiExtended or MultiSimple as you need.
Then write this code in SelectedIndexChanged event of your ListBox:
List<string> orderedSelection = new List<string>();
bool flag = true;
private void listBox3_SelectedIndexChanged(object sender, EventArgs e)
{
if (flag)
{
flag = false;
var list1 = listBox3.SelectedItems.Cast<string>().ToList();
if (listBox3.SelectedItems.Count > orderedSelection.Count)
{
orderedSelection.Add(list1.Except(orderedSelection).First());
}
else if (listBox3.SelectedItems.Count < orderedSelection.Count)
{
orderedSelection.Remove(orderedSelection.Except(list1).First());
}
var list2 = listBox3.Items.Cast<string>().Except(list1).ToList();
listBox3.Items.Clear();
for (int i = 0; i < list1.Count; i++)
{
listBox3.Items.Add(list1[i]);
listBox3.SelectedIndex = i;
}
foreach (string s in list2)
{
listBox3.Items.Add(s);
}
flag = true;
}
}
When user selects an item, It comes to first of the list and the rest of the items comes next.
Also, there is an alternative way. You can use a CheckedListBox with two extra button for moving selected items up and down. So user can change the order of selected items.
This solution uses CheckListBox's ItemCheck event along with a private List to keep track of the click items order.
protected List<string> clickOrderList = new List<string>();
private void Form1_Load(object sender, EventArgs e)
{
// Populate the checked ListBox
this.checkedListBox1.Items.Add("Row1");
this.checkedListBox1.Items.Add("Row2");
this.checkedListBox1.Items.Add("Row3");
this.checkedListBox1.Items.Add("Row4");
}
private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
{
if (sender != null && e != null)
{
// Get the checkListBox selected time and it's CheckState
CheckedListBox checkListBox = (CheckedListBox)sender;
string selectedItem = checkListBox.SelectedItem.ToString();
// If curent value was checked, then remove from list
if (e.CurrentValue == CheckState.Checked &&
clickOrderList.Contains(selectedItem))
{
clickOrderList.Remove(selectedItem);
}
// else if new value is checked, then add to list
else if (e.NewValue == CheckState.Checked &&
!clickOrderList.Contains(selectedItem))
{
clickOrderList.Insert(0, selectedItem);
}
}
}
private void ShowClickOrderButton_Click(object sender, EventArgs e)
{
StringBuilder sb = new StringBuilder();
foreach (string s in clickOrderList)
{
sb.AppendLine(s);
}
MessageBox.Show(sb.ToString());
}
C# TextBox
AutoCompleteCustomSource has a List<string>,
AutoCompleteMode = Suggest.
I can see the List when I type a Letter.
How to show entire list without Typing a Letter Programmatically? This must be done while the User presses the Down Arrow Key in the TextBox.
Is there any Win32 API Available?
My Solution
I refined a Better Solution.
Add a ListBox Control to the form and make it as Visible = false
int curSelIndex = -1;
The below given Code will be executed Form_Load Event.
txtEmpId.AutoCompleteCustomSource.AddRange(EmpIds.ToArray());
lstAutoComplete.Items.Clear();
lstAutoComplete.Items.AddRange(EmpIds.ToArray());
txtEmpId.KeyDown += (ks, ke) =>
{
if (!(ke.KeyCode == Keys.Down ||
ke.KeyCode == Keys.Up ||
ke.KeyCode == Keys.Enter))
{
lstAutoComplete.Visible = false;
return;
}
ke.Handled = true;
if (ke.KeyCode == Keys.Enter)
{
if (lstAutoComplete.Visible)
{
var str = lstAutoComplete.SelectedItem + "";
// Process the Selected Item and set to TextBox.
}
}
if (!lstAutoComplete.Visible && txtEmpId.Focused)
{
var loc = txtEmpId.Location;
loc.Y += txtEmpId.Height;
lstAutoComplete.Location = loc;
lstAutoComplete.Size = txtEmpId.Size;
lstAutoComplete.Height = 100;
lstAutoComplete.SelectedIndex = 0;
curSelIndex = 0;
lstAutoComplete.Visible = true;
}
else if(lstAutoComplete.Visible && txtEmpId.Focused)
{
if (ke.KeyCode == Keys.Down)
{
curSelIndex++;
if (curSelIndex >= lstAutoComplete.Items.Count)
curSelIndex = lstAutoComplete.Items.Count - 1;
if (lstAutoComplete.Items.Count > 0)
lstAutoComplete.SelectedIndex = curSelIndex;
}
else if (ke.KeyCode == Keys.Up)
{
curSelIndex--;
if (curSelIndex < 0)
curSelIndex = 0;
if (lstAutoComplete.Items.Count > 0)
lstAutoComplete.SelectedIndex = curSelIndex;
}
}
};
txtEmpId.Leave += (ls, le) => lstAutoComplete.Visible = false;
I didn't find any API for your problem, so I just make a my own suggestion box by using ListBox to show when the Down Arrow Key is pressed, when you do other operation, it disappeares. I hope it is useful to you. code sample is bellow:
//string datasource
List<string> strList = null;
//suggestion listbox
ListBox sugBox = null;
public FrmTextSuggest()
{
InitializeComponent();
//setting the textbox control
strList = new List<string>()
{
"USA",
"England",
"China",
"Japan",
"Korea",
"India",
"France",
"Canada"
};
var autoCollection = new AutoCompleteStringCollection();
autoCollection.AddRange(strList.ToArray());
this.txtCountry.AutoCompleteCustomSource = autoCollection;
this.txtCountry.AutoCompleteMode = AutoCompleteMode.Suggest;
this.txtCountry.AutoCompleteSource = AutoCompleteSource.CustomSource;
//register the Down Arrow Key event
this.txtCountry.KeyDown += new KeyEventHandler(txtCountry_KeyDown);
}
void txtCountry_KeyDown(object sender, KeyEventArgs e)
{
//show the your own suggestion box when pressing down arrow and the text box is empty
if (e.KeyCode == Keys.Down && txtCountry.Text.Trim().Equals(""))
{
sugBox = new ListBox();
//define the box
sugBox.Width = txtCountry.Width;
Point p = txtCountry.Location;
p.Y += txtCountry.Height;
sugBox.Location = p;
sugBox.Items.AddRange(strList.ToArray());
//copy the value to the textbox when selected index changed.
sugBox.SelectedIndexChanged += new EventHandler(sugBox_SelectedIndexChanged);
//show box
if (sugBox.Items.Count > 0)
{
sugBox.SelectedIndex = 0;
this.Controls.Add(sugBox);
sugBox.Focus();
}
}
//remove and hide your own suggestion box when other operation
else
{
if (sugBox != null && this.Controls.Contains(sugBox))
{
this.Controls.Remove(sugBox);
sugBox.Dispose();
sugBox = null;
}
}
}
void sugBox_SelectedIndexChanged(object sender, EventArgs e)
{
string selText = this.sugBox.SelectedItem.ToString();
if (!string.IsNullOrEmpty(selText))
{
this.txtCountry.Text = selText;
}
}
here is my result of test: