i have two list boxes in my form and a button in between these two boxes. In the first box i binded some data from the database and from this list box i have to select the items and should display those selected items in the second list box. this should happen when i click a button.i used the following code.i used a hash table.
private void btnCATAdd_Click(object sender, EventArgs e)
{
Hashtable ht = new Hashtable();
ht.Add(lbCATallSubcat.SelectedValue.ToString(),
lbCATallSubcat.Text.ToString());
int i = 0;
foreach (string ent in ht.Values)
{
string[] name = new string[lbCATallSubcat.Items.Count];
for (i = 0; i < lbCATallSubcat.SelectedItems.Count; i++)
{
name[i] = lbCATallSubcat.Text;
this.lbCATSelectedSubcat.Items.Add(name[i]);
}
lbCATSelectedSubcat.DisplayMember = ht.Values.ToString();
lbCATSelectedSubcat.ValueMember = ht.Keys.ToString();
}
}
well its working fine when im selecting only single item in the first list box but im unable to display when more than one item is selectd from the first list box
You should use SelectedItems property on that listbox instead SelectedValue. Currently your Hashtable contains only one element.
See http://msdn.microsoft.com/en-us/library/system.windows.forms.listbox.selecteditems.aspx
Add all selected value in hashtable using loop
private void btnCATAdd_Click(object sender, EventArgs e)
{
Hashtable ht = new Hashtable();
for(int i=0;i<lbCATallSubcat.Items.Count;i++)
{
if(ht.items[i].Selected)
{
ht.Add(lbCATallSubcat.Items[i].Value.ToString(),
lbCATallSubcat.Items[i].Text.ToString());
}
}
i = 0;
foreach (string ent in ht.Values)
{
string[] name = new string[lbCATallSubcat.Items.Count];
for (i = 0; i < lbCATallSubcat.SelectedItems.Count; i++)
{
name[i] = lbCATallSubcat.Text;
this.lbCATSelectedSubcat.Items.Add(name[i]);
}
lbCATSelectedSubcat.DisplayMember = ht.Values.ToString();
lbCATSelectedSubcat.ValueMember = ht.Keys.ToString();
}
}
Do you need the Hashtable? With LINQ, you can do something like:
public ObjHoldingData
{
public Display { get; set; }
public Value { get; set; }
}
public class Form
{
Form()
{
var dataList = new List<ObjHoldingData>();
//TODO: Fill list with all the data you pulled
Listbox1.Datasource = dataList;
Listbox1.DisplayMember = "Display";
Listbox1.ValueMember = "Value";
}
protected void ButtonClick()
{
Listbox2.Datasource = Listbox1.SelectedItems.Cast<ObjHoldingData>().ToList();
Listbox2.DisplayMember = "Display";
Listbox2.ValueMember = "Value";
}
}
If you still need the Hashtable you can do this at the start of the button click:
var ht = new Hashtable(ListBox1.SelectedItems.Cast<ObjHoldingData>().ToDictionary(o => o.Display, o => o.Value));
Related
I am trying to come up with a solution where I can search items inside a combo box that contain certain word/phrase. I tried using the AutoComplete text box functionality, but that only searches for the first word which is no good to me.
I have followed the example provided at https://social.msdn.microsoft.com/Forums/vstudio/en-US/4c229a73-cdad-4fa3-95db-97f9ff7810c1/autocomplete-match-on-contains-not-startswith?forum=netfxbcl
I have initiated 2 lists
public List<string> listOnit = new List<string>();
public List<string> listNew = new List<string>();
I then load the data into a comboBox
if (rdr.HasRows == true)
{
// var source = new List<string>();
while (rdr.Read())
{
// myCollectionSales.Add(rdr[0].ToString());
listOnit.Add(rdr[0].ToString());
}
rdr.Close();
//textBox1.AutoCompleteCustomSource = myCollectionSales;
comboBox1.Items.AddRange(listOnit.ToArray());
}
and have a TextUpdate event handler to filter the list when text has changed
private void comboBox1_TextUpdate(object sender, EventArgs e)
{
comboBox1.Items.Clear();
listNew.Clear();
foreach (var item in listOnit)
{
if (item.Contains(this.comboBox1.Text))
{
listNew.Add(item);
}
}
comboBox1.Items.AddRange(listNew.ToArray());
comboBox1.SelectionStart = this.comboBox1.Text.Length;
Cursor = Cursors.Default;
comboBox1.DroppedDown = true;
}
I am coming across a problem where the search results don't return what I expect. For example, I search for the string "Bud" and I only get the following results
http://prntscr.com/ppkatd
While in the database, there is also Budweiser 33cl and Keg Budweiser (http://prntscr.com/ppkbu4), for example, which is fetched on the first list.
Should I be using a different method, rather than "Contains"?
Perhaps you are using different cases?
Try with .ToLower():
private void comboBox1_TextUpdate(object sender, EventArgs e)
{
comboBox1.Items.Clear();
listNew.Clear();
foreach (var item in listOnit)
{
if (item.ToLower().Contains(this.comboBox1.Text.ToLower()))
{
listNew.Add(item);
}
}
comboBox1.Items.AddRange(listNew.ToArray());
comboBox1.SelectionStart = this.comboBox1.Text.Length;
Cursor = Cursors.Default;
comboBox1.DroppedDown = true;
}
I am making a Windows Forms App that manages a hotel. It has Client, Room, Occupancy classes. Client and Rooms have an ArrayList that is populated at runtime from a .txt file that is then displayed in a clientListView and a roomDataGridView.
As such, I have this line of code to populate the roomsDGV:
roomsDGV.DataSource = roomsArrayList;
With the roomsDGV, I'm trying to add new Rows by clicking on the roomsDGV, like when it is NOT databound. I am also trying to edit the rows and save it to txt file after editing or as I'm editing. I can post more code as necessary but I'm not sure if showing more code will help at the current moment. In the end, I'm trying for a functionality so that I can highlight a client in the list and click on one of the rows in roomsDGV and assign that clientID to that room or any sort of way like that.
On load, the datagridview is loaded and formatted correctly from the arrayList but I seem to be having this problem of being able to edit the datagridview. It gives me this error when I click on one of the rows:
System.IndexOutOfRangeException: 'Index -1 does not have a value.'
This stems from Application.Run(new HotelManager());
Here is the form:
public partial class HotelManager : Form
{
// VARIABLES
string clientID;
// FILEPATHS
string clientsTxt = "Clients.txt";
string occupanciesTxt = "Occupancies.txt";
string roomsTxt = "Rooms.txt";
string clientsDat = "Clients.dat";
// ARRAYLIST FOR ROOMS and CLIENTS
ArrayList roomsArrayList = new ArrayList();
ArrayList clientsArrayList = new ArrayList();
//STACKS AND QUEUES INIT
// Load occupancies into stack > pop
Stack roomStack = new Stack();
Queue vacancyQueue = new Queue();
// RANDOM for ID
private readonly Random rand = new Random();
public HotelManager()
{
InitializeComponent();
}
private void HotelManager_Load(object sender, EventArgs e)
{
roomsDGV.DataSource = roomsArrayList;
// LOAD clients
// LoadClients();
RefreshClientList();
// LOAD rooms
LoadRooms();
}
private void NewClientButton_Click(object sender, EventArgs e)
{
AddClient();
}
private void checkInButton_Click(object sender, EventArgs e)
{
string clientID = clientList.SelectedItems[0].Text;
string[] text = File.ReadAllLines(occupanciesTxt);
foreach (string s in text)
{
if (s.Contains(clientID))
{
var replace = s;
Console.WriteLine(s);
replace = replace.Replace("false", "true");
}
}
File.WriteAllLines(occupanciesTxt, text);
}
// METHODS
private void AddClient()
{
//COLLECT DATA > CREATE NEW client > SHOW IN **PROGRAM/DataGridView** > add to clients file
// ID GENERATION > CHECKS AGAINST clientsTXT
clientID = rand.Next(0, 999999).ToString();
if (File.ReadLines(clientsTxt).Contains(clientID))
{
clientID = rand.Next(0, 999999).ToString();
}
Client client = new Client(clientID, firstNameBox.Text, lastNameBox.Text);
try
{
if (!string.IsNullOrWhiteSpace(phoneNumBox.Text))
{
client.PhoneNumber = Convert.ToInt64(phoneNumBox.Text);
}
if (!string.IsNullOrWhiteSpace(addressBox.Text))
{
client.Address = addressBox.Text;
}
}
catch (Exception)
{
MessageBox.Show("Please use the correct format!");
throw;
}
clientsArrayList.Add(client);
using (StreamWriter file =
new StreamWriter("Clients.txt", true))
{
file.WriteLine(client.ToString());
}
RefreshClientList();
// TEST CODE // SERIALIZATION TO .DAT
SerializeClientData(client);
}
private void LoadClients()
{
// LOADS arrayList FROM .txt FILE
List<string> clientList = File.ReadAllLines(clientsTxt).ToList();
foreach (var c in clientList)
{
Client client = new Client(c);
clientsArrayList.Add(client);
}
}
private void LoadRooms()
{
List<string> roomsList = File.ReadAllLines(roomsTxt).ToList();
foreach (var r in roomsList)
{
var roomDetails = r.Split('|');
if (r.Contains("BASIC"))
{
BasicRoom basic = new BasicRoom();
basic.RoomNumber = roomDetails[0];
basic.NumberOfBeds = Convert.ToInt32(roomDetails[1]);
basic.Balcony = Convert.ToBoolean(roomDetails[2]);
basic.DownForRepair = Convert.ToBoolean(roomDetails[3]);
basic.Smoking = Convert.ToBoolean(roomDetails[4]);
roomsArrayList.Add(basic);
}
else if (r.Contains("SUITE"))
{
Suite suite = new Suite();
suite.RoomNumber = roomDetails[0];
suite.NumberOfBeds = Convert.ToInt32(roomDetails[1]);
suite.Balcony = Convert.ToBoolean(roomDetails[2]);
suite.DownForRepair = Convert.ToBoolean(roomDetails[3]);
suite.NumberOfRooms = Convert.ToInt32(roomDetails[4]);
roomsArrayList.Add(suite);
}
}
roomStack = new Stack(roomsArrayList);
foreach (var item in roomStack)
{
Console.WriteLine(item);
}
}
private void RoomsDGV_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
private void RoomsDGV_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
}
}
So far I've looked through all the properties but I can't seem to find the right one. I know I can add/use comboboxes and etc to add a new item into the arrayList instead but I'm trying for datagridview functionality
I expect to edit and add rows to the DGV, but something in the designer is preventing me?
Here is the DGV, and clicking on any of the rows breaks it.
https://imgur.com/a/GG7ZwdV
check this
Insert, Update, Delete with DataGridView Control in C# (Windows Application) | A Rahim Khan's Blog
Insert, Update and Delete Records in a C# DataGridView
Good Luck
I want to see whatever I see in my comboboxcell in other cell only for the current row I'm trying something like this with no result:
dataGridView1.Rows[0].Cells[0].Value =
dataGridView1.Rows[0].Cells[1].Value;\\ cell 1 is my comboboxcell
I have a class named with Item to add items in List,
Item class;
public class Item
{
public string Name { get; set; }
public int Id { get; set; }
}
In Form_Load, I loaded datagridview,
private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.Columns.Add("test1", "test1");
DataGridViewComboBoxColumn testCol = new DataGridViewComboBoxColumn();
testCol.HeaderText = "comboValues";
dataGridView1.Columns.Add(testCol);
dataGridView1.Columns.Add("test2", "test1");
List<Item> items = new List<Item>();
items.Add(new Item() { Name = "One", Id = 1 });
items.Add(new Item() { Name = "Two", Id = 2 }); // created two Items
var cbo = dataGridView1.Columns[1] as DataGridViewComboBoxColumn; // index of 1 is the comboboxColumn
cbo.DataSource = items; // setting datasource
cbo.ValueMember = "Id";
cbo.DisplayMember = "Name";
dataGridView1.Rows.Add("", items[1].Id, "test1");
dataGridView1.Rows.Add("", items[0].Id, "test2");
dataGridView1.Rows.Add("", items[1].Id, "test3"); // and test rows
}
We need to check which row is the previous one before new selection, so we need to use Row_Leave event.
int previousRowIndex = 0; // a variable to keep the index of row
private void dataGridView1_RowLeave(object sender, DataGridViewCellEventArgs e)
{
previousRowIndex = e.RowIndex;
}
And the main event is SelectionChanged,
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
dataGridView1.Rows[previousRowIndex].Cells[0].Value = ""; // first set the previous row's first cell value empty string.
DataGridViewComboBoxCell comboCell = dataGridView1.CurrentRow.Cells[1] as DataGridViewComboBoxCell;
dataGridView1.CurrentRow.Cells[0].Value = comboCell.EditedFormattedValue; // then set the first cell's value as the combobox's selected value.
}
Result;
Hope helps,
I have a DataGridView with a ComboBox column.
The ComboBox gets filled with a specific list of names and they are identical for every row in the DataGridView.
After I fill my DataGridView, I would like to do the following:
I want every Combo’s value to be set to the corresponding row’s “Table Columns” value, if exists.
I.e. in the picture above I want the value of the first Combo to be “id” (if it contains an item named “id”), the second to be “firstname”, etc.
If the value is not found, it should not select any value in the ComboBox.
Update: My current code that is not working
private void Mappings_Load(object sender, EventArgs e)
{
dgv.DataSource = tableColumns.Select(x => new { Value = x }).ToList();
dgv.Columns[0].HeaderText = "Table Columns";
DataGridViewComboBoxColumn comboColumn = new DataGridViewComboBoxColumn();
comboColumn.HeaderText = "File Columns";
foreach (var item in fileColumns)
comboColumn.Items.Add(item);
dgv.Columns.Add(comboColumn);
foreach(DataGridViewRow row in dgv.Rows)
{
string tableColumnValue = row.Cells[0].Value.ToString();
row.Cells[0].Value = tableColumnValue;
}
}
Trace the change .. you almost did it
private void Form1_Load(object sender, EventArgs e)
{
string[] tableColumns = new string[] { "A", "B", "C", "D" };
string[] fileColumns = new string[] { "A", "B", "C", "X" };
dgv.DataSource = tableColumns.Select(x => new { Value = x }).ToList();
dgv.Columns[0].HeaderText = "Table Columns";
DataGridViewComboBoxColumn comboColumn = new DataGridViewComboBoxColumn();
comboColumn.HeaderText = "File Columns";
foreach (var item in fileColumns)
comboColumn.Items.Add(item);
dgv.Columns.Add(comboColumn);
foreach (DataGridViewRow row in dgv.Rows)
{
string tableColumnValue = row.Cells[0].Value.ToString();
//Change is here
if (fileColumns.Any(i => i == tableColumnValue))
{
row.Cells[1].Value = tableColumnValue;
}
//end change
}
}
A while ago I did a similar thing:
Recognize which fields are of type enum
For the fiels of type enum, show a ComboBoxin the cell of the DataGridView (containing all the possible values of the enum) instead of the simple text field.
I think you only need to change certain parts of the code to transform it to what you are trying to achieve:
public partial class TableView<CollectionType, ItemType> : Form
{
public TableView(CollectionType elements)
{
InitializeComponent();
// custom:
this.DataGridView.DataSource = elements;
AdaptColumnsToColumnValueType();
}
private void AdaptColumnsToColumnValueType()
{
for (int columnIndex = 0; columnIndex < this.DataGridView.Columns.Count; columnIndex++)
{
var column = (DataGridViewColumn)this.DataGridView.Columns[columnIndex];
if (column.ValueType.IsEnum)
{
ReplaceColumnInDatagridView(
oldColumn: column,
newColumn: CreateComboBoxWithEnums(column));
}
}
}
private void ReplaceColumnInDatagridView(DataGridViewColumn oldColumn, DataGridViewColumn newColumn)
{
int columnIndex = oldColumn.Index;
this.DataGridView.Columns.Remove(oldColumn);
this.DataGridView.Columns.Insert(columnIndex, newColumn);
}
private DataGridViewComboBoxColumn CreateComboBoxWithEnums(DataGridViewColumn replacedEnumColumn)
{
var comboboxColumn = new DataGridViewComboBoxColumn();
comboboxColumn.DataSource = Enum.GetValues(replacedEnumColumn.ValueType);
comboboxColumn.DataPropertyName = replacedEnumColumn.DataPropertyName;
comboboxColumn.Name = replacedEnumColumn.Name;
return comboboxColumn;
}
}
you can use the DataGridViews RowsAdded event.
Edit: cmb is your ComboBoxColumn
private void dataGridView1_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e) {
//Check if comboboxcolumn contains the value
if(cmb.Items.Contains(dataGridView1.Rows[e.RowIndex].Cells[0].Value)) {
//Set the value
dataGridView1.Rows[e.RowIndex].Cells["cmb"].Value = dataGridView1.Rows[e.RowIndex].Cells[0].Value;
}
}
I need to generate 3 DropDownList Boxes in a row Dynamically on ADD Button click event. Once the DDL is generated i should be able to assign Data source to it and also do DDL-selectedEventChanged functionality on them in c# asp.net.
Below link was exactly am looking for but i couldn't assign data source or i couldn't do any functionality
"Adding multiple DropDownLists with a button click"
any better Ideas please help
if i press Button i need to get 3 DDLs at a time, if i press again it should generate again, so number of clicks= no. of rows with three DDL's in each row
Here is the sample code. The only trick is that you need to load those dynamic controls again after post back. Otherwise, you won't be able to access those.
<asp:PlaceHolder runat="server" ID="PlaceHolder1"></asp:PlaceHolder>
<asp:Button runat="server" ID="AddButton" OnClick="AddButton_Click" Text="Add" />
private List<int> _controlIds;
private List<int> ControlIds
{
get
{
if (_controlIds == null)
{
if (ViewState["ControlIds"] != null)
_controlIds = (List<int>)ViewState["ControlIds"];
else
_controlIds = new List<int>();
}
return _controlIds;
}
set { ViewState["ControlIds"] = value; }
}
private List<string> DataSource
{
get { return new List<string> { "One", "Two", "Three" }; }
}
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
var dataSource = DataSource;
foreach (int id in ControlIds)
{
var ddl = new DropDownList();
ddl.ID = id.ToString();
foreach (var data in dataSource)
ddl.Items.Add(new ListItem(data));
PlaceHolder1.Controls.Add(ddl);
}
}
}
protected void AddButton_Click(object sender, EventArgs e)
{
var dataSource = DataSource;
for (int i = 0; i < 3; i++)
{
var reqs = ControlIds;
int id = ControlIds.Count + 1;
reqs.Add(id);
ControlIds = reqs;
var ddl = new DropDownList();
ddl.ID = id.ToString();
foreach (var data in dataSource)
ddl.Items.Add(new ListItem(data));
PlaceHolder1.Controls.Add(ddl);
}
}