Add Items to Columns in a Wpf Listview

Add Items to Columns in a WPF ListView


Solution With Less XAML and More C#

If you define the ListView in XAML:

<ListView x:Name="listView"/>

Then you can add columns and populate it in C#:

public Window()
{
// Initialize
this.InitializeComponent();

// Add columns
var gridView = new GridView();
this.listView.View = gridView;
gridView.Columns.Add(new GridViewColumn {
Header = "Id", DisplayMemberBinding = new Binding("Id") });
gridView.Columns.Add(new GridViewColumn {
Header = "Name", DisplayMemberBinding = new Binding("Name") });

// Populate list
this.listView.Items.Add(new MyItem { Id = 1, Name = "David" });
}

See definition of MyItem below.

Solution With More XAML and less C#

However, it's easier to define the columns in XAML (inside the ListView definition):

<ListView x:Name="listView">
<ListView.View>
<GridView>
<GridViewColumn Header="Id" DisplayMemberBinding="{Binding Id}"/>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
</GridView>
</ListView.View>
</ListView>

And then just populate the list in C#:

public Window()
{
// Initialize
this.InitializeComponent();

// Populate list
this.listView.Items.Add(new MyItem { Id = 1, Name = "David" });
}

See definition of MyItem below.

MyItem Definition

MyItem is defined like this:

public class MyItem
{
public int Id { get; set; }

public string Name { get; set; }
}

Add Items to Columns in a WPF ListView in Code

Try This Method

      <ListView x:Name="lstvItemsList">
<ListView.View>
<GridView>
<GridViewColumn Header="Id" DisplayMemberBinding="{Binding itemName}"/>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding value}"/>
</GridView>
</ListView.View>
</ListView>

Then create a structure for hold values

    public struct Items
{
public string itemName { get; set; }
public string value { get; set; }
}

Then bind values like this

       lstvItemsList.Items.Add(new Items
{
itemName ="item1" ,
value = "125"
}

How to add item in Listview on WPF

You should initialize the object collection in your code, for example Employees.

Imports System.ComponentModel
Imports System.Collections.ObjectModel

Public Class EmployeeInformation
Public Property FirstName As String
Public Property LastName As String
Public Property EmployeeNumber As Integer
End Class

Class MainWindow
Public Property Employees As ObservableCollection(Of EmployeeInformation)

Public Sub New()
' This call is required by the designer.
InitializeComponent()

' Add any initialization after the InitializeComponent() call.
InitEmploeesCollection(10)
DataContext = Me
End Sub

Private Sub InitEmploeesCollection(count As Integer)
Employees = New ObservableCollection(Of EmployeeInformation)()

For index = 1 To count
Employees.Add(New EmployeeInformation() With {
.FirstName = "FirstName" & index,
.LastName = "LastName" & index,
.EmployeeNumber = index})
Next
End Sub
End Class

And then you can simply bind it to the ListView:

<ListView ItemsSource="{Binding Path=Employees}">
<ListView.View>
<GridView AllowsColumnReorder="True" ColumnHeaderToolTip="Employee Information">
<GridViewColumn Header="First Name" Width="100" DisplayMemberBinding="{Binding Path=FirstName}"/>
<GridViewColumn Header="Last Name" Width="100" DisplayMemberBinding="{Binding Path=LastName}"/>
<GridViewColumn Header="Employee No." Width="100" DisplayMemberBinding="{Binding Path=EmployeeNumber}"/>
</GridView>
</ListView.View>
</ListView>

To initialize columns dynamically, you can add the code from your question. It doesn't make difference if you are taking data from database. Just fill in Employees collection and bind it to the ListView.

Imports System.ComponentModel
Imports System.Collections.ObjectModel

Class MainWindow

Public Property Employees As ObservableCollection(Of EmployeeInformation)

Public Sub New()

' This call is required by the designer.
InitializeComponent()

' Add any initialization after the InitializeComponent() call.
InitEmploeesCollection(10)
SetGridViewDynamically()
DataContext = Me

End Sub

Private Sub InitEmploeesCollection(count As Integer)
Employees = New ObservableCollection(Of EmployeeInformation)()

For index = 1 To count
Employees.Add(New EmployeeInformation() With {
.FirstName = "FirstName" & index,
.LastName = "LastName" & index,
.EmployeeNumber = index})
Next
End Sub

Private Sub SetGridViewDynamically()
Dim myGridView As New GridView
myGridView.AllowsColumnReorder = True
myGridView.ColumnHeaderToolTip = "Employee Information"

Dim gvc1 As New GridViewColumn
gvc1.DisplayMemberBinding = New Binding("FirstName")
gvc1.Header = "FirstName"
gvc1.Width = 100
myGridView.Columns.Add(gvc1)

Dim gvc2 As New GridViewColumn
gvc2.DisplayMemberBinding = New Binding("LastName")
gvc2.Header = "Last Name"
gvc2.Width = 100
myGridView.Columns.Add(gvc2)

Dim gvc3 As New GridViewColumn()
gvc3.DisplayMemberBinding = New Binding("EmployeeNumber")
gvc3.Header = "Employee No."
gvc3.Width = 100
myGridView.Columns.Add(gvc3)

ListView1.View = myGridView
End Sub
End Class

Public Class EmployeeInformation
Public Property FirstName As String
Public Property LastName As String
Public Property EmployeeNumber As Integer
End Class

This way XAML will look like this.

<ListView Name="ListView1" ItemsSource="{Binding Path=Employees}"/>

Add several columns into WPF ListView control

Updated code to create WPF ListView columns and data display from code behind(C#). Hope this may help you:

List<string> countryList = new List<string>();
countryList.Add("Select country");
countryList.Add("USA");
countryList.Add("Germany");

var layoutGridView = new GridView(); //Create layout for ListView.

// Create Display Template and Bindings
FrameworkElementFactory nameFactory = new FrameworkElementFactory(typeof(TextBlock));
nameFactory.Name = "tbkName";
nameFactory.SetBinding(TextBlock.TextProperty, new Binding("Name")); // Assign Property Binding paths for the collection bound to ListView.

FrameworkElementFactory comboFactory = new FrameworkElementFactory(typeof(ComboBox));
comboFactory.Name = "cmbCountry";
comboFactory.SetValue(ComboBox.ItemsSourceProperty, countryList); // Assign default list to display in dropdown.
comboFactory.SetBinding(ComboBox.SelectedValueProperty, new Binding("Country")); // Assign value to select from dropdown.

FrameworkElementFactory checkBoxFactory = new FrameworkElementFactory(typeof(CheckBox));
checkBoxFactory.Name = "chkSelected";
checkBoxFactory.SetValue(CheckBox.IsCheckedProperty, new Binding("IsSelected"));

//Define columns with the corresponding cell templates
layoutGridView.Columns.Add(new GridViewColumn
{
Header = "Name",
CellTemplate = new DataTemplate
{
VisualTree = nameFactory //First(text) column display template
}
});

layoutGridView.Columns.Add(new GridViewColumn
{
Header = "State",
CellTemplate = new DataTemplate
{
VisualTree = comboFactory //Second(Combobox) column display template
}
});

layoutGridView.Columns.Add(new GridViewColumn
{
Header = "Is Selected",
CellTemplate = new DataTemplate
{
VisualTree = checkBoxFactory //Third(Checkbox) column display template
}
});

listView1.View = layoutGridView; // Assign the display template to ListView.

//Data Binding to listview.
List<MyData> data = new List<MyData>
{
new MyData { Name="Abc", Country= "USA", IsSelected=true},
new MyData { Name="Def", Country= "Germany", IsSelected=false}
};

listView1.ItemsSource = data; //Assign data to ListView's ItemsSource property.

WPF & ListView - Adding Columns and Items @ Runtime


<ListView x:Name="ListViewControl">
<ListView.View>
<GridView x:Name="GridViewControl"/>
</ListView.View>
</ListView>

and in code behind,

ListViewControl.ItemsSource = ItemsSourceObject;   //your query result 
GridViewColumn column = new GridViewColumn();
column.Header = "Name";
column.DisplayMemberBinding = new Binding("Name");
GridViewControl.Columns.Add(column);

Add columns and rows to wpf listview dynamically

So, what i was looking for is described in this thread.
He creates a new Dictionary-class, which implements the INotifyPropertyChanged interface.
When adding data to the dictionary an event is triggered.

At the place in your code where you want to add a new row, you just put the data into an object of this Dictionary class and add the Dictionary to an ObservableCollection which is bound to the DataGrid.

Adding items in WPF ListView with columns

WPF does not bind to fields, only to properties. Flag, Name and IpAddress are defined as public fields on your class. Change the class definition to use auto properties instead:

public class ServerListItem 
{
public string Flag { get; set; }
public string Name { get; set; }
public string IpAddress { get; set; }
}

Adding items to ListView GridView in C# WPF

As you are assigning the same collection to the items source again, WPF will not refresh the ListView. There are different ways to achieve what you want, but the best one is to use the ObservableCollection<T> instead of List<T>. In this case you even do not need your refresh method, as the ListView will be updated automatically as soon as you add a new item to the observable collection.

How do I add, save and load items to a listview in WPF

I just updated your structure (I used a class, just force of habit) to use automatic property values which are available in recent versions of VS. The default implementation of properties is built in along with the backer fields. It is used just as before.

You are on the right track with ObservableCollection but you you need to implement INotifyPropertyChanged by adding the Event PropertyChanged and providing the Sub OnPropertyChanged to raise the event.

Set up the bindings on the controls and set the ItemsSource ot the ListView to your ObservableList.

To save Import System.Text so you can use a StringBuilder. The loop through the list to build the string to save to a text file.

I didn't spend any time trying to make the XAML Windows look nice. Pardon the ugliness.

Class MainWindow
Public Songs As New ObservableCollection(Of Song)

Protected Sub OnLoad(sender As Object, e As RoutedEventArgs)
Songs.Add(New Song("Nirvana", "Smells Like Teen Spirit", "Open"))
Songs.Add(New Song("John Lennon", "Imagine", "In Stock"))
Songs.Add(New Song("U2", "One", "Unknown"))
Songs.Add(New Song("Michael Jackson", "Billie Jean", "Open"))
lvSongs.ItemsSource = Songs
End Sub

Private Sub BtnAdd_Click(sender As Object, e As RoutedEventArgs)
Dim frm As New frmAdd
frm.mainForm = Me 'send the instance of the current form to the new form
frm.ShowDialog()
End Sub

Private Sub SaveList()
Dim sb As New StringBuilder
For Each item As Song In Songs
sb.AppendLine($"{item.Artist}|{item.Title}|{item.Status}")
Next
'call sb.ToString and write it to a .txt file
End Sub
End Class

MainWindow XAML

<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPF_BindComboBox"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid Loaded="OnLoad"
Name="root">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>

</Grid.RowDefinitions>
<ListView Margin="10" Name="lvSongs" Grid.Row="0">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="Name: " />
<TextBox x:Name="txtArtist"
Text="{Binding Artist, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
FontWeight="Bold"/>
<TextBlock Text=", " />
<TextBlock Text="Age: " />
<TextBox Text="{Binding Title}"
FontWeight="Bold" />
<TextBlock Text=" (" />
<TextBox Text="{Binding Status}" />
<TextBlock Text=")" />
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button x:Name="btnAdd" Grid.Row="1" Height="25" Width="100" Content="Add a Song" Click="BtnAdd_Click"/>
</Grid>
</Window>

The Song class

Public Class Song
Implements INotifyPropertyChanged

Public Property Artist() As String
Public Property Title() As String
Public Property Status() As String

Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

Protected Sub OnPropertyChanged(ByVal name As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(name))
End Sub

Public Sub New(art As String, Ttl As String, Stat As String)
Artist = art
Title = Ttl
Status = Stat
End Sub
End Class

The Add Window

Public Class frmAdd

Public mainForm As MainWindow

Private Sub BtnAdd_Click(sender As Object, e As RoutedEventArgs)
mainForm.Songs.Add(New Song(txtArtist.Text, txtTitle.Text, txtStatus.Text))
ClearForm()
End Sub

Private Sub ClearForm()
txtArtist.Clear()
txtTitle.Clear()
txtStatus.Clear()
End Sub

End Class

Add Window XAML

<Window x:Class="frmAdd"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPF_BindComboBox"
mc:Ignorable="d"
Title="frmAdd" Height="172.641" Width="307.547">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" Text="Artist" FontSize="16" FontWeight="Bold"/>
<TextBox x:Name="txtArtist" Grid.Column="1" Grid.Row="0" FontSize="16" Width="150" />
<TextBlock Grid.Column="0" Grid.Row="1" Text="Title" FontSize="16" FontWeight="Bold"/>
<TextBox x:Name="txtTitle" Grid.Column="1" Grid.Row="1" FontSize="16" Width="150"/>
<TextBlock Grid.Column="0" Grid.Row="2" Text="Status" FontSize="16" FontWeight="Bold"/>
<TextBox x:Name="txtStatus" Grid.Column="1" Grid.Row="2" FontSize="16" Width="150"/>
<Button x:Name="btnAdd" Grid.Column="1" Grid.Row="4" Content="Add Song" Click="BtnAdd_Click"/>
</Grid>
</Window>

EDIT
Required Imports

Imports System.Collections.ObjectModel
Imports System.ComponentModel
Imports System.Text


Related Topics



Leave a reply



Submit