How to make a dynamic ListView in wpf?
-
Tuesday, June 09, 2009 7:07 AM
Well i can have a normal listview and databind it to a my sql.
<ListView> <ListView.View> <GridView> <GridViewColumn Width="140" Header="Column 1" /> <GridViewColumn Width="140" Header="Column 2" /> <GridViewColumn Width="140" Header="Column 3" /> </GridView> </ListView.View> </ListView>
but what happen if i want to show diffrent data on the same list view for example:
I want to show Last sell data which has 4 columns, Employee info which has 10 columns.
if i hard code the column names the way i done above i can not succeed.any idea?
All Replies
-
Tuesday, June 09, 2009 8:08 AMHi Salomon112,
the easiest way would be to define a DataTemplate for each collection type. What kind of control is the parent of the ListView? -
Tuesday, June 09, 2009 8:12 AM
Hi Guenter,
My ListView is inside a Grid.
How about column header names? in ASP:Net we have GridView which help with these issues a lot. -
Tuesday, June 09, 2009 2:00 PMTo show different type of columns you can use a DataTemplateSelector, you have more info here:
http://msdn.microsoft.com/en-us/library/system.windows.controls.datatemplateselector.selecttemplate.aspx
http://www.switchonthecode.com/tutorials/wpf-tutorial-how-to-use-a-datatemplateselector
I'm not sure if you can do somethig about the header names, but maiby you have to define a grouping and put the header s in each group. -
Sunday, June 14, 2009 3:22 PM
Hi Salomon112,
you could use column names as header for example:
C#:DataTable dt = this.LoadDataTable(); _listView.DataContext = dt; _gridView.Columns.Clear(); foreach (var colum in dt.Columns) { DataColumn dc = (DataColumn)colum; GridViewColumn column = new GridViewColumn(); column.DisplayMemberBinding = new Binding(dc.ColumnName); column.Header = dc.ColumnName; _gridView.Columns.Add(column); }
Hope it helps.- Marked As Answer by Jim Zhou - MSFT Monday, June 15, 2009 11:18 AM
-
Monday, June 15, 2009 11:17 AM
Hi,
-->but what happen if i want to show diffrent data on the same list view for example:I want to show Last sell data which has 4 columns, Employee info which has 10 columns.
As far as I know, there is no direct approach that can set more than one DataTables as data source to ListView. As a workaround, you can firstly wrap the DataTables by using an ObservableCollection class, the bind the ObservableCollection instance to the ItemsSource property of ListView.
-->How about column header names? in ASP:Net we have GridView which help with these issues a lot.
you can use property of class to specify the GridViewColumn’header as Guenter Schwaiger mentioned above. Set the DisplayMemberBinding property of GridViewColumn. As a result, you can bind multiple DataTables to ListView.
Hope this helps.
Thanks.
Jim Zhou -MSFT- Marked As Answer by Jim Zhou - MSFT Monday, June 15, 2009 11:18 AM
-
Friday, July 09, 2010 9:37 PM
I know this question is a little old, but like Salomon112 I'm trying to implement a ListView which can show a data table with an arbitrary number of columns. The code here looks very promising. I made a sandbox project to try it out, and I can get the right number of columns and rows, and I get the headers in the table, but the actual data does not show up in the cells. (FYI I'm using .NET 3.5sp1) Why doesn't the data show up? Here's my code:
Window1.xaml
<Window x:Class="DynamicListViewGrid.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> <StackPanel> <ListView x:Name="_listView"> <ListView.View> <GridView x:Name="_gridView"/> </ListView.View> </ListView> </StackPanel> </Grid> </Window>
Window1.xaml.cs
public partial class Window1 : Window { public Window1() { InitializeComponent(); DataTable exampleTable = new DataTable(); exampleTable.Columns.Add("Alpha"); exampleTable.Columns.Add("Beta"); exampleTable.Rows.Add("a1", "b1"); exampleTable.Rows.Add("a2", "b2"); exampleTable.AcceptChanges(); loadTable(exampleTable); } private void loadTable(DataTable dt) { //_listView.DataContext = dt; // Setting the ItemSource instead of the DataContext // causes the table to have the right number of rows. _listView.ItemsSource = dt.Rows; _gridView.Columns.Clear(); foreach (var colum in dt.Columns) { DataColumn dc = (DataColumn)colum; GridViewColumn column = new GridViewColumn(); column.DisplayMemberBinding = new Binding(dc.ColumnName); column.Header = dc.ColumnName; _gridView.Columns.Add(column); } } }
- Proposed As Answer by TonyBye Monday, July 12, 2010 1:34 PM
-
Monday, July 12, 2010 1:33 PM
One small change in the xaml OR the csharp fixes this.
In xaml change to this (add the ItemSource binding):
<ListView x:Name="_listView" ItemsSource="{Binding}"> <ListView.View> <GridView x:Name="_gridView"/> </ListView.View> </ListView>
- OR -
In csharp change to this:
private void loadTable(DataTable dt) { _gridView.Columns.Clear(); _listView.DataContext = dt; // Setting ItemSource directly does not work! //_listView.ItemsSource = dt.Rows; // Bind the ItemsSourceProperty to {Binding} Binding bind = new Binding(); _listView.SetBinding(ListView.ItemsSourceProperty, bind);
-
Monday, November 22, 2010 12:31 PM
What is - _gridView, how do we get instance of it from the ListView control ?
-
Thursday, November 25, 2010 1:03 PM
I have created a ListView with dynamic columns, under these columns there are checkboxes, i was able to databind these checkboxes with the underlying datatable. Pls see the complete code below:- XAML.cs
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Documents;using System.Windows.Input;
using System.Windows.Media;using System.Windows.Media.Imaging;using System.Windows.Shapes;
using System.IO;using System.Windows.Markup;using System.Data;namespace WpfListView
{
/// <summary>
/// Interaction logic for SalesPerson_SalesRegion_Association.xaml
/// </summary>
public partial class SalesPerson_SalesRegion_Association : Window
{
public SalesPerson_SalesRegion_Association()
{
InitializeComponent();
AddColumnsToListView();
DataTable dt = DataHelper.GetRegionPersonAssociation();
listView1.ItemsSource = dt.DefaultView;
}private void btnShow_Click(object sender, RoutedEventArgs e)
{
DataView view = listView1.ItemsSource as DataView;
DataTable userSelectionTbl = view.ToTable();DataTable idTable = DataHelper.GetRegionIdPersonIdMatrix();
List<SalesRegion> lstRegion = SalesRegion.GetRegions();string selectedRegion = string.Empty;
string msg = string.Empty;
DataRow dRow=null;int totRows = userSelectionTbl.Rows.Count;
int totCols = lstRegion.Count-1;
string strTempMsg = string.Empty;
bool isColChecked = false;
for (int rowIndex = 0; rowIndex < totRows; rowIndex++)
{
dRow = userSelectionTbl.Rows[rowIndex];
strTempMsg = dRow[0].ToString() + "(" + idTable.Rows[rowIndex][0].ToString() + ")" + " : ";
string rgnId="";
isColChecked = false;
foreach (SalesRegion region in lstRegion)
{
if (((bool)dRow[region.RegionName]) == true)
{
rgnId = idTable.Rows[rowIndex][region.RegionName].ToString();
strTempMsg += region.RegionName + "(" + rgnId + ")";
isColChecked = true; }
}
if (isColChecked == false)
{
strTempMsg += " : No region selected";
}
strTempMsg += Environment.NewLine;msg += strTempMsg;
}textBlock1.Text = msg;
string tt = "t";
}
private void AddColumnsToListView()
{
List<SalesRegion> lstSalesRegion = SalesRegion.GetRegions();
List<SalesPerson> lstSalesPerson = SalesPerson.GetSalesPersons();GridViewColumn colSalesPerson = new GridViewColumn();
colSalesPerson.Header = "Sales Person";
colSalesPerson.DisplayMemberBinding = new Binding("SalesPersonName");
colSalesPerson.Width = 150;
GridView grdView = listView1.View as GridView;
grdView.Columns.Add(colSalesPerson);//Since columns are dynamic we need a data template per column
// in which we bind the checkBox's checked property with
//appropriate columnName
Dictionary<string, DataTemplate> dict = GetDataTemplates(lstSalesRegion);foreach (SalesRegion region in lstSalesRegion)
{
GridViewColumn col1 = new GridViewColumn();
col1.Header = region.RegionName;
DataTemplate dTempl = dict[region.RegionName];
col1.CellTemplate = dTempl;
grdView.Columns.Add(col1);
}
}private Dictionary<string, DataTemplate> GetDataTemplates(List<SalesRegion> lstSalesRegion)
{
Dictionary<string, DataTemplate> dict = new Dictionary<string, DataTemplate>();
foreach (SalesRegion region in lstSalesRegion)
{
DataTemplate dTemplate = CreateDataTemplate(region.RegionName);
dict.Add(region.RegionName, dTemplate);
}
return dict;
}
private DataTemplate CreateDataTemplate(string propName)
{
MemoryStream sr = null;
ParserContext pc = null;
string xaml = string.Empty;
xaml = "<DataTemplate><CheckBox VerticalAlignment=\"Center\" IsChecked=\"{Binding " + propName + "}\"></CheckBox></DataTemplate>";
sr = new MemoryStream(Encoding.ASCII.GetBytes(xaml));
pc = new ParserContext();
pc.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
pc.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
DataTemplate datatemplate = (DataTemplate)XamlReader.Load(sr, pc);
return datatemplate;
}} // class ends here
} // DataHelper classesusing System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Data;
namespace WpfListView
{
public class SalesPerson
{
public int SalesPersonId
{ get; set; }
public string SalesPersonName
{ get; set; }public SalesPerson(int salesPersonId, string salesPersonName)
{
this.SalesPersonId = salesPersonId;
this.SalesPersonName = salesPersonName;
}public static List<SalesPerson> GetSalesPersons()
{
List<SalesPerson> lst = new List<SalesPerson>();
lst.Add(new SalesPerson(101, "SalesPerson1"));
lst.Add(new SalesPerson(201, "SalesPerson2"));
lst.Add(new SalesPerson(301, "SalesPerson3"));
lst.Add(new SalesPerson(401, "SalesPerson4"));
lst.Add(new SalesPerson(501, "SalesPerson5"));
return lst;
}
} // class SalesPerson ends herepublic class SalesRegion
{
public int RegionId
{ get; set; }
public string RegionName
{ get; set; }public SalesRegion(int regionId, string regionName)
{
this.RegionId = regionId;
this.RegionName = regionName;
}
public static List<SalesRegion> GetRegions()
{
List<SalesRegion> lst = new List<SalesRegion>();
lst.Add(new SalesRegion(501,"North"));
lst.Add(new SalesRegion(502, "South"));
lst.Add(new SalesRegion(503, "East"));
lst.Add(new SalesRegion(504, "West"));
lst.Add(new SalesRegion(505, "MyRegion"));
return lst;
}
} // class SalesRegion ends herepublic class DataHelper
{
public static DataTable GetRegionPersonAssociation()
{
DataTable dt = new DataTable();
//Create data table structure
// SalesPerson Region1 Region2 Region3 ....
DataColumn colSalesPerson = new DataColumn("SalesPersonName", typeof(string));
dt.Columns.Add(colSalesPerson);List<SalesRegion> lstRegions = SalesRegion.GetRegions();
DataColumn colRegion = null;
foreach (SalesRegion region in lstRegions)
{
colRegion = new DataColumn(region.RegionName, typeof(bool));
dt.Columns.Add(colRegion);
}
//Fill data into the data table
List<SalesPerson> personList = SalesPerson.GetSalesPersons();
DataRow dRow = null;
foreach (SalesPerson sp in personList)
{
dRow = dt.NewRow();
dRow["SalesPersonName"] = sp.SalesPersonName;
foreach (SalesRegion sr in lstRegions)
{
dRow[sr.RegionName] = false;
}
dt.Rows.Add(dRow);
}
return dt;
}public static DataTable GetRegionIdPersonIdMatrix()
{
DataTable dt = new DataTable();//Create data table structure
// SalesPerson Region1 Region2 Region3 ....
DataColumn colSalesPerson = new DataColumn("SalesPersonId", typeof(int));
dt.Columns.Add(colSalesPerson);List<SalesRegion> lstRegions = SalesRegion.GetRegions();
DataColumn colRegion = null;
foreach (SalesRegion region in lstRegions)
{
colRegion = new DataColumn(region.RegionName, typeof(int));
dt.Columns.Add(colRegion);
}
//Fill data into the data table
List<SalesPerson> personList = SalesPerson.GetSalesPersons();
DataRow dRow = null;
foreach (SalesPerson sp in personList)
{
dRow = dt.NewRow();
dRow["SalesPersonId"] = sp.SalesPersonId;
foreach (SalesRegion sr in lstRegions)
{
dRow[sr.RegionName] = sr.RegionId;
}
dt.Rows.Add(dRow);
}
return dt;
} } // class DataHelper ends here
} // namespace ends here -
Thursday, November 25, 2010 1:04 PM
Please see the XAML file for the above (Dynamic column list view code)
<Window x:Class="WpfListView.SalesPerson_SalesRegion_Association"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="SalesPerson_SalesRegion_Association" Height="500" Width="500">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<ListView Name="listView1" Width="400" Height="300" Margin="20" HorizontalAlignment="Left">
<ListView.View>
<GridView></GridView>
</ListView.View>
</ListView>
<Button Grid.Row="1" HorizontalAlignment="Left"
Content="ShowSelectedMapping"
Name="btnShow" Width="150" Margin="0,10,0,0" Click="btnShow_Click"></Button>
<TextBlock Name="textBlock1" Grid.Row="2"
HorizontalAlignment="Left" Margin="0,10,0,0"></TextBlock>
</Grid>
</Window> -
Sunday, August 05, 2012 10:20 AM
hey sunil. This is working grt as i wanted. really a grt thank u. But the thing is i need textbox with numbers instead of checkbox which is to be binded from database. Now if the number is changed. i want the changed number with everything u display wen u click on the button selected items. Hope to hear from you.

