I have problem with creating listview I have tried different methods of filling ListView items from SQL Server and I can not solve it.
I created this function to fill the listview dynamically, the connection works so far, so thats not the problem. But currently my problem is, the function creates the row but they remain Empty while the header list work correctly.
I am writing the following code
XAML:
<ListView Name="LV" Height="494" Margin="10,30,10,10">
<ListView.View>
<GridView>
<GridViewColumn/>
</GridView>
</ListView.View>
</ListView>
C#
SqlDataAdapter sqladp = new SqlDataAdapter(query, strCon);
DataSet ds = new DataSet();
sqladp.Fill(ds, dValue);
DataTable dt = ds.Tables[0];
// Add columns
var gridView = new GridView();
LV.View = gridView;
for (int i = 0; i < dt.Columns.Count; i++)
{
gridView.Columns.Add(new GridViewColumn
{
Header = dt.Columns[i].ToString(),
DisplayMemberBinding = new Binding($"[{i}]")
});
}
if (dt.Rows.Count > 0)
//Add Row
foreach (DataRow row in dt.Rows)
{
string[] arr = new string[dt.Columns.Count];
ListViewItem itm;
try
{
for (int i = 0; i < dt.Columns.Count; i++)
arr[i] = row[i].ToString();
LV.Items.Add(arr);
}
catch
{
}
}
LV.Visibility = Visibility.Visible;
You're assigning rowItems to Content, but rowItems is empty and remains empty. Perhaps you meant to assign Content to arr, which you fill up but then do nothing with it.
Also, you don't need to create the ListViewItems yourself. They're created for you when you add items to the ListView.Items property. Change that part of the code to the following (based on your updated code):
for (int i = 0; i < dt.Columns.Count; i++)
arr[i] = row[i].ToString();
LV.Items.Add(arr);
Finally, because you're adding an array (rather than an object with properties), you need to fix the column's binding to the following:
gridView.Columns.Add(new GridViewColumn
{
Header = dt.Columns[i].ToString(),
DisplayMemberBinding = new Binding($"[{i}]")
});
Related
What's the equivalent in .NET to convert my DataGrid to a DataTable (DataGrid.ItemsSource isn't defined in .Net csharp.
Thanks!
DataTable dt = new DataTable();
dt = ((DataView)DataGrid1.ItemsSource).ToTable();
EDIT
This isn't a duplicate since the previous code is for WPF and I'm looking for an asp.net mvc csharp answer.
The ItemsSource is for WPF. Use the DataSource and cast it to DataTable like this:
dt = (DataTable)DataGrid1.DataSource;
EDIT: And if you get into trouble with above approach, you can use a custom method like this:
private DataTable ToDataTable(DataGridView dataGridView)
{
var dt = new DataTable();
foreach (DataGridViewColumn dataGridViewColumn in dataGridView.Columns)
{
if (dataGridViewColumn.Visible)
{
dt.Columns.Add();
}
}
var cell = new object[dataGridView.Columns.Count];
foreach (DataGridViewRow dataGridViewRow in dataGridView.Rows)
{
for (int i = 0; i < dataGridViewRow.Cells.Count; i++)
{
cell[i] = dataGridViewRow.Cells[i].Value;
}
dt.Rows.Add(cell);
}
return dt;
}
And then use it:
var dataTable = ToDataTable(dataGridView1);
Also MoreLinq is a good choice in case the type of Datasource is a list. Check this solution to know how to use it: https://stackoverflow.com/a/42550827/2946329
If you are referring to the System.Windows.Forms.DataGrid or System.Web.UI.WebControls.DataGrid, then the best way would be to cast the Datasource property to a DataTable.
Of course the Datasource property has to actually be a DataTable underlying type to begin with. You need to know the underlying type of the object stored in the Datasource property.
If the underlying type of Datasource is a generic list, then this SO post should help: How to convert a list into data table
FYI - The Windows Forms DataGrid control, according to Microsoft, has been replaced by the DataGridView.
if there is visible columns in datagridview you can use
private DataTable ToDataTable(DataGridView dataGridView)
{
var dt = new DataTable();
int columnCount = 0;
List<int> columnNumbers= new List<int>();
foreach (DataGridViewColumn dataGridViewColumn in dataGridView.Columns)
{
if (dataGridViewColumn.Visible)
{
dt.Columns.Add(dataGridViewColumn.Name);
columnNumbers.Add(columnCount);
}
columnCount++;
}
var cell = new object[columnNumbers.Count];
foreach (DataGridViewRow dataGridViewRow in dataGridView.Rows)
{
int i = 0;
foreach (int a in columnNumbers)
{
cell[i] = dataGridViewRow.Cells[a].Value;
i++;
}
dt.Rows.Add(cell);
}
return dt;
}
The custom method does not take into account the hidden columns. You are getting an error, because you have too many cells for the columns copied.
You can use :
int dgv1RowCount = dgv1.Rows.Count;
int numOfColumns = dgv1.Columns.GetColumnCount(DataGridViewElementStates.Visible) ;
int numCells = dgv1RowCount * numOfColumns;
// use numCells in the for loop
for (int i = 0; i < numOfCells ; i++)
{
enter code here
}
I have been able to make one existing column combo box column in the datagridview, how do I do it for several columns? Also how do I add existing distinct records in the combobox items? The user will be able to either choose value from combobox item or write their own. So far my code is:
dgvLoadTable.DataSource = null;
var context = new CadAdminEntities();
var TableName = cboSelectTable.Text.ToString();
var rawData = context.GetType().GetProperty(TableName).GetValue(context, null);
var truncatedData = ((IQueryable<object>)rawData).Take(0);
var source = new BindingSource { DataSource = truncatedData };
dgvLoadTable.DataSource = source;
dgvLoadTable.ReadOnly = false;
dgvLoadTable.AllowUserToAddRows = true;
DataGridViewComboBoxCell dgvCol = new DataGridViewComboBoxCell();
for (int row= 0; row < dgvLoadTable.Rows.Count; row++)
{
for (int col = 0; col < dgvLoadTable.Columns.Count; col++)
{
if(col==2||col==4)
this.dgvLoadTable[col,row] = dgvCol;
//This part throws error, as there is only one combobox
}
}
dgvLoadTable.Refresh();
This is easy to fix:
this.dgvLoadTable[col, row] = new DataGridViewComboBoxCell();
will create a fresh ComboBoxCell for each case.
You can delete the line
DataGridViewComboBoxCell dgvCol = new DataGridViewComboBoxCell();
Note that since you have a Databound DGV and the Columns were probably created automatically, you should keep in mind, that often one needs to switch off that automatism and create all column manually before setting the DataSource..
I have problem with creating listview. I am new in C# and wpf too.
I have tried different methods of filling ListView items and I can not solve it, because the input array is NxN dimensions. I found instructions on Bindig but I can not apply them because I can not create an object of that type, because the input array is dynamic.
I can fill header columns but no rows and columns with values. This code works but all values are together in one column.
public void PrintListView(ResultsTable results)
{
System.Windows.Controls.GridView gv = new System.Windows.Controls.GridView();
gv.AllowsColumnReorder = true;
int j=0;
foreach (DataColumn dc in results.Columns)
{
GridViewColumn gvCol = new GridViewColumn();
gvCol.Header = results.Columns[j].ColumnName;
gvCol.Width = 200;
gv.Columns.Add(gvCol);
j++;
}
lbVysledky.View = gv;
foreach (DataRow dr in results.Rows)
{
string[] array1 = new string[1000];
// List<string> zoznam = new List<string>();
// ObservableCollection<string> kolekcia = new ObservableCollection<string>();
int i = 0;
foreach (DataColumn dc in results.Columns)
{
array1[i] = dr[dc].ToString();
// zoznam.Add (dr[dc].ToString());
// kolekcia.Add(dr[dc].ToString());
i++;
}
this.lbVysledky.Items.Add(new ListViewItem { Content = pole[0] + pole[1]});
}
}
Can someone help me? Thanks
It looks like you're trying to populate the ListView by adding rows and columns one at a time. This is not the approach to use when populating a ListView. Instead, you add the ItemsSource (in this case, your results object) and tell the ListView what the DisplayMemberBinding is for each column, and it will display the proper values in each column for each row.
It probably just means modifying your loop where you add columns to the ListView to something like this:
foreach (DataColumn dc in results.Columns)
{
GridViewColumn gvCol = new GridViewColumn();
gvCol.DisplayMemberBinding = new Binding(dc.ColumnName);
gvCol.Header = results.Columns[j].ColumnName;
gvCol.Width = 200;
gv.Columns.Add(gvCol);
j++;
}
lbVysledky.View = gv;
Then just set the ItemsSource of the ListView to your results object like this:
lbVysledky.ItemsSource = results;
Also, as a side note, you don's appear to be using the foreach construct correctly. you're enumerating over each column, but you're keeping your own counter and accessing the column like this:
gvCol.Header = results.Columns[j].ColumnName;
In a foreach loop, you're already enumerating the columns with the dc variable, so you can access the column like this:
gvCol.Header = dc.ColumnName;
and you don't need to manually count the columns (with j).
In my xml file,it has many elements and many child/sub child elements are there so i have decided to load as generic list and display in the DGView and the columns are already created/customed in DGview.
I have to edit the values in the datagridview and serialize back to the file. I would like to know,
how can i get the values from the datagrid view and serialize back to the file.
I tried using this, Dataset ds = new Dataset();ds = (Dataset) (dataGridView2.Datasource);ds.WriteXml("XML_File.xml"); i got a error message, nullRefExceptionError.
As I know the DataSet ds is null, thats why I'm getting this error.
I don't want to use the dataset for binding.I want to bind the xml file directly to the datagridview. IS it possible with my approach???
This approach is good but it's not saving the xml file as like the original xml file:
DataTable dt = new DataTable("Rules");
for (int i = 0; i < dataGridView4.ColumnCount; i++)
{
dt.Columns.Add(dataGridView4.Columns[i].Name, typeof(System.String));
}
DataRow myrow;
int icols = dataGridView4.Columns.Count;
foreach (DataGridViewRow drow in this.dataGridView4.Rows)
{
myrow = dt.NewRow();
for (int i = 0; i <= icols - 1; i++)
{
myrow[i] = drow.Cells[i].Value;
}
dt.Rows.Add(myrow);
}
dt.WriteXml(#"C:\test\items.xml");
Any help for me to serilaize/write the values from datagridview.
I have adapted this approach for my problem & it works.
List<Test>laneConfigs = new List<Test>();//From a class
foreach (DataGridViewRow dr in dataGridView1.Rows)
{
int bbbBorder = 0;
Int32.TryParse(dr.Cells["BBor"].Value.ToString(), out bbbBorder );
int eeee= 0;
Int32.TryParse(dr.Cells["EBor"].Value.ToString(), out eee);
LaneConfig laneConfig = new LaneConfig(
dr.Cells["ID"].Value.ToString(),
(TrafficLaneType)Enum.Parse(typeof(TrafficLaneType), dr.Cells["Type"].Value.ToString()),
new ValueWithUnit<int>(bbbBorder, "mm"),
new ValueWithUnit<int>(eee, "mm"));
laneConfigs.Add(llaneConfig);
}
Would someone kindly assist me with the following? I have two DataGridView objects that each display a DataTable, where the two datatables are related with the following code:
DataSet dSet = new DataSet();
DataTable ParentList = ListToDataTable(_listOfAllAlbumObjects);
DataTable ChildList = ListToDataTable(_listOfAllTrackObjects);
dSet.Tables.AddRange(new DataTable[]{ParentList, ChildList});
DataColumn parentRelationColumn = ParentList.Columns["AlbumId"];
DataColumn childRelationColumn = ChildList.Columns["AlbumId"];
dSet.Relations.Add("ParentToChild", parentRelationColumn, childRelationColumn);
ParentDataGridView.DataSource = dSet;
ParentDataGridView.DataMember = "ParentList";
ChildDataGridView.DataSource = ???;
ChildDataGridView.DataMember = "ParentToChild";
Both DataTables are actually List<> converted to DataTables with the following:`
public static DataTable ListToDataTable<T>( IList<T> data)
{
var props = TypeDescriptor.GetProperties(typeof(T));
var table = new DataTable();
for (var i = 0; i < props.Count; i++)
{
PropertyDescriptor prop = props[i];
table.Columns.Add(prop.Name, prop.PropertyType);
}
var values = new object[props.Count];
foreach (T item in data)
{
for (int i = 0; i < values.Length; i++)
{ values[i] = props[i].GetValue(item); }
table.Rows.Add(values);
}
return table;
}
Initially it appears that the each DataGridView displays the data appropriately; however the child DataGridView does not update with any change of record in the parent DataGridView.
I see that the tables need to be interconnected through the binding-source; however I don't believe there is a true binding-source here.
Could someone please steer me in the right direction? Thanks.
There's an MSDN article showing what you want to do:
How to: Create a Master/Detail Form Using Two Windows Forms DataGridView Controls
Here's how this might work for you:
Either through the designer or through code add two BindingSources to your project: parentBindingSource and childBindingSource. Then try this in place of the code you have.
// Associate your BSs with your DGVs.
ParentDataGridView.DataSource = parentBindingSource;
ChildDataGridView.DataSource = childBindingSource;
// (Most of) your code here:
DataSet dSet = new DataSet();
DataTable ParentList = ListToDataTable(_listOfAllAlbumObjects);
DataTable ChildList = ListToDataTable(_listOfAllTrackObjects);
dSet.Tables.AddRange(new DataTable[]{ParentList, ChildList});
DataColumn parentRelationColumn = ParentList.Columns["AlbumId"];
DataColumn childRelationColumn = ChildList.Columns["AlbumId"];
dSet.Relations.Add("ParentToChild", parentRelationColumn, childRelationColumn);
// Let's name this DT to make clear what we're referencing later on.
ParentList.TableName = "ParentListDT";
// Rather than set the data properties on your DGVs, set them in your BindingSources.
parentBindingSource.DataSource = dSet;
parentBindingSource.DataMember = "ParentListDT";
childBindingSource.DataSource = parentBindingSource;
childBindingSource.DataMember = "ParentToChild";