I have a GridView in which the user can select rows he wants to copy (move it to another grid view). up until now, the user had to select each row one by one. I want to improve the UX by letting the user select multiple rows at once and copy multiple rows.
Is there any way I can do this in an easy way?
The image shows what i want to do, move the selected rows to the right grid view I am using C# WPF and the data is stored in a Datatable which is linked to the grid view
The code I used for moving one line:
DataRowView viewRow = (DataRowView)DBElementGrid.SelectedItem;
DataRow row = selectTable.NewRow();
for (int i = 0; i < DBElementGrid.Columns.Count; i++)
{
row[i] = viewRow[i];
}
selectTable.Rows.Add(row);
for (int i = 0; i < DBElementGrid.Columns.Count; i++)
{
selectTable.Columns[i].ColumnName = DBElementGrid.Columns[i].Header.ToString();
}
selectGrid.DataContext = selectTable.DefaultView;
This should work provided that the right DataGrid (targetDataGrid) is bound to a DataView that contains the same number of columns as the original one that you select from:
DataView dv = targetDataGrid.ItemsSource as DataView;
if (dv != null)
{
foreach (var selectedItem in selectGrid.SelectedItems.OfType<DataRowView>())
{
dv.Table.Rows.Add(selectedItem.Row.ItemArray);
}
}
You can directly access the selected Items of the dataGrid in case you are using DataGrid. So DataGrid.SelectedItems will give you the selected items which you can set as the items source for the right DataGrid.
Related
My end goal is to populate a DataGrid with data retrieved from a database at runtime. My methodology is to pull all the columns from that database first and then pull the corresponding data for each column for each row as below:
ReadOnlyCollection<Field> tablefields = {//has the fields populated from the database};
//adding all the columns to the data table
var datatable = new DataTable("mytable");
foreach (var field in tablefields)
{ datatable.Columns.Add(field.Name, wFieldType); }
//Then add the rows
while (cursor.MoveNext())
{
var tableRow = datatable.NewRow();
var row = cursor.Current;
for(var i = 0; i < tablefields.Count; i++)//add the values for each field to the data table.
{
tableRow[i] = row[i] ?? DBNull.Value;
}
datatable.Rows.Add(tableRow);
}
My problem however is that some of the columns that I am pulling have to be in the form of a DataGridComboBoxColumn since they have preset values in a dropdown list in the database. The best case scenario would have been that as I pull the columns into my dataTable one by one, I would detect the ones that have preset values and make those oftype DataGridComboBoxColumn before adding them to the dataTable. I obviously can't do that because you cannot have a combobox on a dataTable. My next option is to use the dataGrid to load the columns and the data from the database at runtime.
I am able to add the columns with a combobox as shown in the code below but I cannot figure out how to get my data from the database into the dataGrid containing the pre-loaded columns.
DataGridComboBoxColumn cb = new DataGridComboBoxColumn();
cb.ItemsSource = new List(){to be populated later}
cb.Header = field.Name;
MyDataGrid.Columns.Add(cb);
The code above was used as a sample to test the DataGridComboBoxColumn and sure enough I was able to see the datagrid with the comboboxes. I just can't figure out how to get my database data into the table. I would appreciate any ideas.
PS: I cannot use datagridview because of the api that I am working with so I am limited to datagrid.
You should set the SelectedItemBinding to a binding to a column in your DataTable that contains the value in the ItemsSource to be selected:
cb.SelectedItemBinding = new Binding("AColumnInYourDataTable");
If you set the ItemsSource to a List<T> where T is a complex type, you should instead set the SelectedValueBinding and SelectedValuePath and DisplayMemberPath properties:
cb.SelectedValueBinding = new Binding("AColumnInYourDataTable");
cb.SelectedValuePath = "NameOfThePropertyOfTThatHoldsTheValue";
cb.DisplayMemberPath = "NameOfAPropertyOfTThatHoldsTheDisplayName";
I have a ListView object in Asp.Net (C#) where I also have a ListView_ItemDataBound() method that is populated using a sqlDataSource.
In some cases, I would like to be able to insert a row in the ListView prior to the current record being bound. I.e., as the rows are being populated, I need to be able to read the value that is about to be bound and then insert a "header" row mid stream before the current row of data is added to the ListView.
In the case of the ItemDataBound event, the data seems to be already bound to the control so the rows being added are actually one ListView row too late for me to do anything.
ListView_ItemDataBound()
{
System.Data.DataRowView rowView = e.Item.DataItem as System.Data.DataRowView;
//Pseudo code of what I'd like
//if rowView["some_field"]==123 then
// insert row prior to this row being bound
}
I'm relatively new to Asp.Net and come from a classic asp background so maybe I'm thinking and going about this all wrong. Any suggestions would be appreciated.
Instead of doing that after you've already assigned the datasource and called listView.DataBind() you should do that in the datasource. Presuming it's a DataTable:
List<int> rowIndices = new List<int>();
for(int i = 0; i < dataTable.Rows.Count - 1; i++)
{
int some_field = dataTable.Rows[i].Field<int>("some_field");
if (some_field == 123)
rowIndices.Add(i + rowIndices.Count); // indices will increases by count
}
foreach(int index in rowIndices)
{
DataRow newRow = ....
dataTable.Rows.InsertAt(newRow, index);
}
Now assign this modified table as datasource and call DataBind.
I have an application with multiple datagridviews in a tabcontrol.
One of the tabcontrols has 4 columns that are filled by the datasource.
I don't use autogenerate columns, but use the DataPropertyName to bind values to the columns.
I also have 2 columns i create, wich are filled manually, after assigning the DataSource.
Values in this datagridview are filtered values from a datagridview somewhere else in the application.
When i filter, then go to the tab containing the datagridview, the manual columns are empty.
Changing the filter (but not the results) fills those colums.
How can i get the columns that are manually filled to always show their values?
Calling Refresh() or Update() on the datagridview doesn't solve my problem
Short version of my code:
I actually use a class that inherits from DataGridView
//fill datagridview
PcbLink[] links = Service.Instance.Client.queryPcbLinks();
List<Pcb> pcbs = new List<Pcb>();
foreach (PcbLink link in links)
{
PcbFilter pcbfilter = new PcbFilter();
pcbfilter.pcb_id = link.pcb_id;
Pcb[] res = Service.Instance.Client.queryPcbs(pcbfilter);
pcbs.Add(res[0]);//only first element because pcb_id should always be unique -> only one row
}
cdgvUsage.SetData(pcbs);//setData is used as cdgvUsage.DataSource = pcbs, but does some stuff internally
for (int i = 0; i < links.Length; i++)
{
SortableBindingList<Pcb> dataSource = cdgvUsage.GetData<Pcb>();
cdgvUsage["count", i].Value = links[i].count;
char variantchar = (char)('a' + (char)(dataSource[0].variant));
cdgvUsage.Columns["variant"].ValueType = typeof(string);
cdgvUsage["variant", i].Value = variantchar.ToString();
}
I believe after asigning DataSource to the dataGridView changes must be saved in datasource also otherwise they will not be reflected in the dataGridView (as it takes data from datasource everytime you do Refresh() or Update()).
Make sure manually filled values are stored in dataSource.
I Have two tables I select a record from table 1 to show information in table 2 on double click in one of information I got window to update data after closing this window I have to refresh the two tables and I want the same row be selected in table 1.
I was working in wpf and I use selectedindex.
Now I use this for the moment:
int index = dgTable1.Grid.CurrentRow.Index;
///**
frm.ShowDialog();
frm.Dispose();
ReloadTable1();
selectedindex(index)
with
private void selectindex(int index)
{
dgwTable1.Grid.Rows[index].Selected = true;
DATAtype data= dgwTable1.GetObjectFromRow<DATAtype>(index);
LoadTable2(data);
}
It work But I have Grid_SelectionChanged for table1 and don't fire i have to reload data, also If the scroll bar is down when I use this I return to the top of table 1!
But I know this not the right way to do it:( and it's too simple in wpf :/
dgTable is a UserControl with a DataGridView as a Grid
To Save Current Index :
int index = dataGridView1.CurrentRow.Index;
After Editing:
dataGridView1.Rows[index].Selected = true;
Hope this helps.
May be DataView and BindingSource with filters better to use?
DataView view = new DataView(_table);
BindingSource tSource = new BindingSource();
tSource.DataSource = view;
_dataGridView.DataSource = _tSource;
_tSource.Filter = "Value=0";
like this...
To save scrolling use myDataGridView.FirstDisplayedScrollingRowIndex
int scrollIndex = 0;
if (myDataGridView.FirstDisplayedScrollingRowIndex >= 0)
scrollIndex = myDataGridView.FirstDisplayedScrollingRowIndex;
after editing:
if (myDataGridView.Rows.Count > 0)
myDataGridView.FirstDisplayedScrollingRowIndex = scrollIndex;
Hope this helps.
In my opinion, the easiest way to solve your problems, is to use the MVVM pattern. In your ViewModel for your View that contains the two DataGrids, you have a property like "SelectedNameOfContentClass" that is bound to first DataGrids SelectedValue-property. This "SelectedNameOfContentClass"-property is also bound to seconds datagrid DataSource. So if you changes the selected row in first DataGrid, the Source of second DataGrid automatically updates.
The list, that is bound to first Datagrids DataSource, should be an ObservableCollection. For the dialog you can use the IEditableObject interface in your objects.
I am trying to move selected rows from one DGV to another DGV at the click of a button.
I really don't know where to begin..
I have two seperate DGVs that are bound by a DataSource..
choiceDGV.DataSource = theChoiceList;
universalDGV.DataSource = theUniversalList;
I would like to move any selected items in the choiceDGV to the univeralDGV by a click of a button. I need to make sure the selected rows are removed from the one DGV and added to the 2nd DGV.
Both of the DataGridView's have the same amount of columns.
Did you try:
foreach (DataGridViewRow row in choiceDGV.SelectedRows)
{
universalDGV.Rows.Add(row);
choiceDGV.Rows.Delete(row);
}
or (edited: DataGridViewRow doesn't have ItemArray unfortunately):
foreach (DataGridViewRow row in choiceDGV.SelectedRows)
{
object[] items = new object [row.Cells.Count];
for (int i = 0; i < row.Cells.Count; i++)
items[i] = row.Cells[i].Value;
universalDGV.Rows.Add(items);
choiceDGV.Rows.Delete(row);
}
I can't see the issue. You just need move the items you like to the UniversalList within the onclick button handler and call .DataBind() on both the datagridview.
In other words you have to hit the lists(datasource) instead of the data grid view