已答复 How to make a dynamic ListView in wpf?

  • 2009年6月9日 7:07
     
      包含代码

    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?

全部回复

  • 2009年6月9日 8:08
     
     
    Hi Salomon112,

    the easiest way would be to define a DataTemplate for each collection type. What kind of control is the parent of the ListView?
  • 2009年6月9日 8:12
     
     

    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.

  • 2009年6月9日 14:00
     
     
    To 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.
  • 2009年6月14日 15:22
     
     已答复 包含代码

    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.

  • 2009年6月15日 11:17
     
     已答复

    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
  • 2010年7月9日 21:37
     
     建议的答复 包含代码

    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);
      }
     }
     }
    
    • 已建议为答案 TonyBye 2010年7月12日 13:34
    •  
  • 2010年7月12日 13:33
     
      包含代码

    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);
    
  • 2010年11月22日 12:31
     
     

    What is  - _gridView, how do we get instance of it from the ListView control ?

  • 2010年11月25日 13:03
     
     

    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 classes

    using 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 here

        public 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 here

        public 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

     

     

     

     

     

     

  • 2010年11月25日 13:04
     
     

    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>

  • 2012年8月5日 10:20
     
     

    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.