I'm trying to find a way to add data from one datagrid to another and for that data to be inserted to only one column at a time in my second datagrid. The specific column is created each time the Add button has been clicked.
My coding so far:
private void btnFeedbackAddSupplier_Click(object sender, RoutedEventArgs e)
{
dgFeedbackSelectSupplier.Items.Clear(); //So that my rows do not stack each other on every add
DataGridTextColumn columnSupplier = new DataGridTextColumn();
columnSupplier.Binding = new Binding("Supplier");
DataGridTextColumn columnFeedbackSupplierItem = new DataGridTextColumn();
//The 'Item' column is binded in XAML
columnSupplier.Header = (cmbFeedbackSelectSupplier.SelectedItem as DisplayItems).Name;
columnSupplier.IsReadOnly = true;
dgFeedbackAddCost.SelectAll(); //Selects all the rows in 1st datagrid
//Casts selected rows to my 'ViewQuoteItemList' class
IList list = dgFeedbackAddCost.SelectedItems as IList;
IEnumerable<ViewQuoteItemList> items = list.Cast<ViewQuoteItemList>();
var collection = (from i in items let a = new ViewQuoteItemList { Item = i.Item, Supplier = i.Cost }
select a).ToList();
//Adds both the column and data to the 2nd datagrid
dgFeedbackSelectSupplier.Columns.Add(columnSupplier);
foreach (var item in collection)
dgFeedbackSelectSupplier.Items.Add(item);
}
My reason for wanting to add the data to only one separate column at a time is because the data is different each time I want to add it to my 2nd datagrid and it overwrites any previous data that was entered in older add's.
EDIT: I Here are some images of what my current problem is
Here I add the first company and it's values. Everything works fine
Here I add the second company with it's new values, but it changes the values entered with the first company. This is my big problem. So you can see how my values are changed from the first to the second image
I think your problem here is that all your columns are bound to the same property: Supplier. Since you're updating that property everytime, all columns are assigned the same value. In the end, there's only one Supplier property for each row, so you can't show a different value for that single property on each column since everytime you change that property's value, the Bindings get notified and update themselves.
Maybe you could try using a OneTime Binding instead of a regular one. That way, the cells would retain the value they had when you first added them to the DataGrid. But for that to work, you should avoid clearing the DataGrid's items list, since re-adding the items would force them to rebind again.
Another option would be having a list of suppliers in your Supplier property, and have each column bind to an index of that list.
private void btnFeedbackAddSupplier_Click(object sender, RoutedEventArgs e)
{
// ...
columnSupplier.Binding = new Binding(string.Format("Supplier[{0}]", supplierColumnIndex));
// ...
var supplierCosts = new List<int>();
// ...
// Fill the list with the Costs of the Suppliers that correspond to each column and item
// ...
var collection = (from i in items let a = new ViewQuoteItemList { Item = i.Item, Supplier = supplierCosts }
select a).ToList();
//Adds both the column and data to the 2nd datagrid
dgFeedbackSelectSupplier.Columns.Add(columnSupplier);
foreach (var item in collection)
dgFeedbackSelectSupplier.Items.Add(item);
}
Related
I have 3 Dropdown Lists (could be more in future).
DropdownList1 is a parent and is populated from a database.
DropdownList2 is a child and is populated from the selected item from DropdownList1.
DropdownList3 is a child and is populated from the selected item from DropdownList2.
I would like to add the selected item to a ListBox.
The problem i have is DropdownList2 and DropdownList3 may not always have a child item, so to add the items to a ListBox, i could store their IDs but display their text.
My database table has 3 columns to save the value (ID) from the 3 dropdown lists.
My question is if i display the text of the item in the ListBox, the next step is to save the data into the table into the relevant columns (so column 1 would save data from DD1, Column 2 would save from DD2 etc) is there anyway to identify which ID the item belongs to, so i can save the correct ID to the correct column?
So a user selects item 1 from DD1 item 2 from DD2, there is no item available from DD3, so they click add which adds the item to the ListBox. When i have to save this item how could i distinguish the item added was upto DD2 therefore it needs to be added to Column2? Or is there a better approach?
Hope this makes sense
List boxes don't like to store multiple values. They can, however, store objects as their datasource.
First create a custom object, then assign the values from each of your dropdown lists to the object:
Declare a new list of your custom object first
List<myObject> list = new List<myObject>();
then assign this to your button:
private void Button1_Click(object sender, EventArgs e)
{
myObject object = new myObject(Dropdown1, Dropdown2, Dropdown3);
list.Add(object);
//assign the list to the Listbox control
ListBox.Datasource = list;
}
When you want to access the values for your query, use a foreach loop to cycle over the objects in the list, with a pointer value to access each of them.
foreach (myObject obj in list)
{
var val1 = list[obj].Dropdown1;
var val2 = list[obj].Dropdown2;
var val3 = list[obj].Dropdown3;
//enter your sql code here
}
Let me know if you want to expand further.
In my DataGrid I used a ComboBox in the first column, so it will fetch some data from the database using the DisplayMember and ValueMember concepts. Now I want to remove the value from the ComboBox which is previously selected.
Populating the ComboBox code is given below:
dTable = getDummyTable.GetDummyTble("Dummy", "DNO", "All");
dCmbData = dTable;
cmbDeno.DataSource = dTable;
cmbDeno.DisplayMember = "dyName";
cmbDeno.ValueMember = "dyRemarks";
The next row of selection there should not be a duplicate value in the ComboBox.
How can I achieve this?
Can anyone help me with this?
well try this one out. You have the DataTable which you are using to bind all combos (correct me if I'm wrong). Now all we need to do is that when an item is selected from any combo, we need to remove that item from all the other combos). You will need to declare a class level dictionary to store which combo had what value stored previously:
IDictionary<ComboBox, DataRow> _prevSelection;
//Please don't mind if syntax is wrong worked too long in web
comboBox.OnSelectedIndexChanged += fixItems;
private void fixItems(object sender, EventArgs e)
{
var cbo= sender as ComboBox;
if(cbo==null) return;
var prev = _prevSelection[cbo];
var row=<GET ROW FROM DATATABLE FOR CURRENT SELECTED VALUE>;
_prevSelection[cbo] = row;
UpdateOtherCombos(cbo, prev, cbo.SelectedItem.Value);
}
private void UpdateOtherCombos(ComboBox cbo, DataRow prev, object toRemove)
{
foreach(var gridrow in <YourGrid>.Rows)
{
var c = <FIND COMBO IN ROW>;
if(cbo.Id == c.Id) continue;//combo that triggered this all
var itemToRemove=null;
foreach(var item in c.Items)
{
if(item.Value == toRemove)
{
itemToRemove = item;
break;
}
}
//or you can get index of item and remove using index
c.Items.Remove(itemToRemove);
//Now add the item that was previously selected in this combo (that
//triggered this all)
c.Items.Add(new ComboBoxItem{Value = prev["ValueColumn"],
Text = prev ["TextColumn"]});
}
}
This is just to give you an idea that may help you to find an optimal solution rather than iterating over all combos as it will slow down if you have too many rows in grid or too many items in combos. Still even with this you need to put up some functions/code to make it working. Also please note that I have not worked on WinForms for some time and you need to check if things like ComboBoxItem etc. and any functions called on them exist. :)
I have table with 4 primary key fields. I load that in to drop down list in my WinForm application created by using C#.
On the TextChanged event of drop down list I have certain TextBox and I want to fill the information recived by the table for the certain field I selected by the drop down list.
So as I say the table having 4 fields. Can I get those all 4 fields into value member from the data set, or could you please tell me whether is that not possible?
Thank you.
Datatable dt=dba.getName();
cmb_name.ValueMember="id";
cmb_name.DisplayMember="name";
cmb_name.DataSource=dt;
this is normal format.. but i have more key fields.. so i need to add more key fields..
You can use DataSource property to bind your source data to the ComboBox (e.g. a List of Entities, or a DataTable, etc), and then set the DisplayMember property of the ComboBox to the (string) name of the field you want to display.
After the user has selected an Item, you can then cast the SelectedItem back to the original row data type (Entity, DataRow, etc - it will still be the same type as you put in), and then you can retrieve your 4 composite keys to the original item.
This way you avoid the SelectedValue problem entirely.
Edit:
Populate as follows:
cmb_name.DisplayMember = "name";
cmb_name.DataSource = dt;
// Ignore ValueMember and Selected Value entirely
When you want to retrieve the selected item
var selectedRow = (cmb_name.SelectedItem as DataRowView );
Now you can retrieve the 4 values of your PK, e.g. selectedRow["field1"], selectedRow["field2"], selectedRow["field3"] etc
If however you mean that you want to DISPLAY 4 columns to the user (i.e. nothing to do with your Table Key), then see here How do I bind a ComboBox so the displaymember is concat of 2 fields of source datatable?
cmb_name.DisplayMember = "name";
cmb_name.DataSource = dt;
DataRowView selectedRow = (cmb_name.SelectedItem as DataRowView );
The result will be here:
MessageBox.Show(selectedRow.Row[0].ToString());
MessageBox.Show(selectedRow.Row[1].ToString());
MessageBox.Show(selectedRow.Row[2].ToString());
MessageBox.Show(selectedRow.Row[3].ToString());
.....
If you want to get some data from a ComboBox in to a List you can use something like this
List<string> ListOfComboData = new List<string>();
ListOfComboData = yourComboBox.Items.OfType<string>().ToList<string>();
I have no real idea if this is what you mean as the question is very poorly structured. I hope this helps...
Edit: To put the selected text in to some TextBox use
yourTextBox.Text = youComboBox.Text;
in the SelectedIndexChanged event of your ComboBox.
You could follow the approach here with the following class:
public class ComboBoxItem
{
public string Text { get; set; }
public object[] PrimaryKey { get; set; }
}
private void Test()
{
ComboboxItem item = new ComboboxItem();
item.Text = "Item text1";
item.PrimaryKey = new object[] { primaryKey1, primaryKey2, primaryKey3, primaryKey4};
comboBox1.Items.Add(item);
comboBox1.SelectedIndex = 0;
MessageBox.Show((comboBox1.SelectedItem as ComboboxItem).Value.ToString());
}
I have one listview whith several columns.
I want to fill this listview in a vertical form
column to column.
Sorry, but this is not (easily) possible.
A ListView has a list of ListViewItems, where each one has a List of ListViewSubItems (and to make it a little more complex at the first spot, the first ListViewSubItem is the same as the ListViewItem itself).
So if you like to fill up a ListView column by column you first have to add the ListViewItems to the ListView for all the values you want in the first column.
Afterwards you iterate through the ListView.Items and call on every ListViewItem.Subitems.Add to fill up the next column. This must be done for each column you like to fill.
If you like to fill in the column values in another order then from left to right, you should take a look into the DisplayIndex of the ColumnHeader within the ListView.Columns.
Some example code:
// Some values
var someValues = Enumerable.Range(1, 10);
// Fill up the first column
foreach (var item in someValues)
{
listView.Items.Add("0." + item);
}
// Run for each column in the listView (the first is already filled up)
foreach (ColumnHeader column in listView.Columns.Cast<ColumnHeader>().Skip(1))
{
// Get the value and the index for which row the value should be
foreach (var item in someValues.Select((Value, Index) => new { Value, Index }))
{
// Add the value to the given row, thous leading to be added as new column
listView.Items[item.Index].SubItems.Add(column.Index + "." + item.Value);
}
}
I'm using a List to bind to a dataGridView.
I'd like the user to be able to add a new row.
I've tried using a BindingList and a BindingSource.
Here's my binding (not including the combo box column I add to the datagridview before adding a datasource:
binding = new BindingSource();
binding.DataSource= _Rows;
_dg.DataSource = binding;
Here's the code that fills _Rows
protected override List<BusinessApp> getRows(DataGridViewManager manager)
{
var dc = manager.dc.DcHerb;
return (from p in dc.apps
where p.zQueueId == this.ZQueueId
select p)
.ToList().ToBusinessApp(dc);
}
Here's what I'm trying to get a new row. No exception occurs, but the dataGridView doesn't appear to change at all, even though _Rows count goes from 68 to 69
private void newRow()
{
_Rows.Add(new BusinessApp(_manager.dc.DcHerb, new app() {acaps="1234" }));
//_dg.DataSource = binding; //tried rebinding here
//_dg.DataSource = _Rows;
}
I would as if you have any foreign key bind to the other table or not, if yes, you may assign a key to the new added row and the datagrid will show the current new added row. Otherwise you may also missing the code datagrid.EndEdit()
How about invoking "AddNew()" method on your "binding" member variable that you have defined already?
binding.AddNew();
// and set the needed columns...
((binding.Current.Row) as <yourTypedDataTableRow>).<columnName> = <someValue>;