none
Add new row to multi-column ListView with VB.NET at runtime

    Question

  • Hi all,

    In my continuing quest to learn WPF programming, I'm playing around with listviews. I'm trying to create a listview with 2 columns that gets populated at runtime (using VB .NET). Here's my XAML definition of the listview:

    <ListView Name="MyListView" Width="Auto">
    	<ListView.View>
    		<GridView x:Name="MyListViewGrid">
    			<GridViewColumn>  
    			</GridViewColumn>
    			<GridViewColumn>
    			</GridViewColumn>
    		</GridView>
    	</ListView.View>
    </ListView>
    

    The View is a Grid (recommended in all the docs I could find). The question is how can I populate the rows? I tried a sequence of adding multiple ListViewItems to the ListView like this:

    Dim NewItem As New ListViewItem
    NewItem.Content = "Test1,1"
    MyListView.Items.Add(NewItem)
    Dim NewItem1 As New ListViewItem
    NewItem1.Content = "Test1,2"
    MyListView.Items.Add(NewItem1)
    Dim NewItem2 As New ListViewItem
    NewItem2.Content = "Test2,1"
    MyListView.Items.Add(NewItem2)
    Dim NewItem3 As New ListViewItem
    NewItem3.Content = "Test2,2"
    MyListView.Items.Add(NewItem3)
    

    but it duplicates each new ListViewItem's content in both columns (e.g. I get 4 rows with 2 columns, each column having the same text in the same row). I tried the old VB trick of creating a 2 element string array and adding the text I want in the 1st column to string element 0, and the text for the 2nd column to element 1, then setting the ListViewItem's Content to the string array, but all that gives me is the words 'String Array[]' in the listview. And since there's no 'SubItems' property in the ListViewItem in WPF I can't use that to add something to the 2nd column.

    Any suggestions on how I can populate (and later reference) both columns in each row in my ListView at runtime? BTW - all the documentation I could find on the subject deals with setting up a data source for the listview columns, which I don't have. I know I'm missing something basic but I can't figure it out.

    Thanx.

    John

     


    John McDonald
    Friday, January 14, 2011 12:28 AM

Answers

  • Hi John,

    while there would of course be a way of dealing with this the "WinForms way", I'd strongly recommend you simply leave that out and rather start thinking "WPF'ish". That is, you don't add items to a control. Instead, you create your own list in code and bind your UI to that list. From there you only need to add item(s) to (or remove them) from that list. I've posted a simple example in this thread which illustrates this with only little code and should thus be easy to grasp. While that sample is using a ListBox, you could apply this to a ListView in just the same fashion.

    Since the sample in the linked thread is in C# and you're using VB, here's a VB version:

    <Window x:Class="ListBox_TextColorBinding"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Title="ListBox_TextColorBinding" Height="300" Width="300">
      <Grid>
       <Grid.RowDefinitions>
         <RowDefinition Height="*"/>
         <RowDefinition Height="Auto"/>
       </Grid.RowDefinitions>
       <ListBox x:Name="lb" ItemsSource="{Binding TheItems}" 
            HorizontalContentAlignment="Stretch" Margin="5">
    
         <ListBox.ItemTemplate>
          <DataTemplate>
            <Border Background="{Binding TheBrush}" 
                CornerRadius="2" Margin="2" Padding="3">
             <TextBlock Text="{Binding TheText}"/>
            </Border>
          </DataTemplate>
         </ListBox.ItemTemplate>
       </ListBox>
       <Button x:Name="cmdAddItems" Grid.Row="1" Content="Add items ..." 
           Click="cmdAddItems_Click" Margin="5"/>
      </Grid>
    </Window>
    
    

     

    Code-behind:

    Option Strict On
    Option Explicit On
    
    
    Imports System
    Imports System.Windows
    Imports System.Windows.Media
    Imports System.Collections.ObjectModel
    
    Public Class ListBox_TextColorBinding
    	'The collection the LB binds to
    	Private _TheItems As observableCollection(Of TheItemsClass)
    	Public Property TheItems As observableCollection(Of TheItemsClass)
    		Get
    			Return _TheItems
    		End Get
    		Set(ByVal value As observableCollection(Of TheItemsClass))
    			_TheItems = value
    		End Set
    	End Property
    
    	Public Sub New()
    		InitializeComponent()
    
    		'Initialize ...
    		TheItems = New ObservableCollection(Of TheItemsClass)
    		'The window binds to this class
    		Me.DataContext = Me
    	End Sub
    
    	Private Sub cmdAddItems_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
    		'Add some items to the collection
    		Dim intStartIndex As Integer = TheItems.Count
    		Dim rnd As New Random()
    		For intCounter As Integer = intStartIndex To intStartIndex + 10 - 1
    			'Simulate either incoming and outgoing ...
    			If CType(rnd.Next(1, 50) Mod 2, Integer) = 0 Then
    				TheItems.Add(New TheItemsClass() With { _
    					 .TheBrush = Brushes.LightGreen, _
    					 .TheText = "Incoming - item #" + intCounter.ToString() _
    					})
    			Else
    				TheItems.Add(New TheItemsClass() With { _
    					 .TheBrush = Brushes.LightPink, _
    					 .TheText = "Outgoing - item #" + intCounter.ToString() _
    					 })
    			End If
    		Next
    	End Sub
    End Class
    
    'A single item displayed in the LB
    Public Class TheItemsClass
    	Private _TheBrush As Brush
    	Private _TheText As String
    
    	Public Property TheBrush As Brush
    		Get
    			Return _TheBrush
    		End Get
    		Set(ByVal value As Brush)
    			_TheBrush = value
    		End Set
    	End Property
    
    	Public Property TheText As String
    		Get
    			Return _TheText
    		End Get
    		Set(ByVal value As String)
    			_TheText = value
    		End Set
    	End Property
    End Class
    

     


    Cheers,
    Olaf
    http://blogs.intuidev.com
    • Proposed as answer by Olaf Rabbachin Friday, January 14, 2011 3:11 PM
    • Marked as answer by John McDonald Friday, January 14, 2011 3:45 PM
    Friday, January 14, 2011 9:24 AM

All replies

  • Hi John,

    while there would of course be a way of dealing with this the "WinForms way", I'd strongly recommend you simply leave that out and rather start thinking "WPF'ish". That is, you don't add items to a control. Instead, you create your own list in code and bind your UI to that list. From there you only need to add item(s) to (or remove them) from that list. I've posted a simple example in this thread which illustrates this with only little code and should thus be easy to grasp. While that sample is using a ListBox, you could apply this to a ListView in just the same fashion.

    Since the sample in the linked thread is in C# and you're using VB, here's a VB version:

    <Window x:Class="ListBox_TextColorBinding"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Title="ListBox_TextColorBinding" Height="300" Width="300">
      <Grid>
       <Grid.RowDefinitions>
         <RowDefinition Height="*"/>
         <RowDefinition Height="Auto"/>
       </Grid.RowDefinitions>
       <ListBox x:Name="lb" ItemsSource="{Binding TheItems}" 
            HorizontalContentAlignment="Stretch" Margin="5">
    
         <ListBox.ItemTemplate>
          <DataTemplate>
            <Border Background="{Binding TheBrush}" 
                CornerRadius="2" Margin="2" Padding="3">
             <TextBlock Text="{Binding TheText}"/>
            </Border>
          </DataTemplate>
         </ListBox.ItemTemplate>
       </ListBox>
       <Button x:Name="cmdAddItems" Grid.Row="1" Content="Add items ..." 
           Click="cmdAddItems_Click" Margin="5"/>
      </Grid>
    </Window>
    
    

     

    Code-behind:

    Option Strict On
    Option Explicit On
    
    
    Imports System
    Imports System.Windows
    Imports System.Windows.Media
    Imports System.Collections.ObjectModel
    
    Public Class ListBox_TextColorBinding
    	'The collection the LB binds to
    	Private _TheItems As observableCollection(Of TheItemsClass)
    	Public Property TheItems As observableCollection(Of TheItemsClass)
    		Get
    			Return _TheItems
    		End Get
    		Set(ByVal value As observableCollection(Of TheItemsClass))
    			_TheItems = value
    		End Set
    	End Property
    
    	Public Sub New()
    		InitializeComponent()
    
    		'Initialize ...
    		TheItems = New ObservableCollection(Of TheItemsClass)
    		'The window binds to this class
    		Me.DataContext = Me
    	End Sub
    
    	Private Sub cmdAddItems_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
    		'Add some items to the collection
    		Dim intStartIndex As Integer = TheItems.Count
    		Dim rnd As New Random()
    		For intCounter As Integer = intStartIndex To intStartIndex + 10 - 1
    			'Simulate either incoming and outgoing ...
    			If CType(rnd.Next(1, 50) Mod 2, Integer) = 0 Then
    				TheItems.Add(New TheItemsClass() With { _
    					 .TheBrush = Brushes.LightGreen, _
    					 .TheText = "Incoming - item #" + intCounter.ToString() _
    					})
    			Else
    				TheItems.Add(New TheItemsClass() With { _
    					 .TheBrush = Brushes.LightPink, _
    					 .TheText = "Outgoing - item #" + intCounter.ToString() _
    					 })
    			End If
    		Next
    	End Sub
    End Class
    
    'A single item displayed in the LB
    Public Class TheItemsClass
    	Private _TheBrush As Brush
    	Private _TheText As String
    
    	Public Property TheBrush As Brush
    		Get
    			Return _TheBrush
    		End Get
    		Set(ByVal value As Brush)
    			_TheBrush = value
    		End Set
    	End Property
    
    	Public Property TheText As String
    		Get
    			Return _TheText
    		End Get
    		Set(ByVal value As String)
    			_TheText = value
    		End Set
    	End Property
    End Class
    

     


    Cheers,
    Olaf
    http://blogs.intuidev.com
    • Proposed as answer by Olaf Rabbachin Friday, January 14, 2011 3:11 PM
    • Marked as answer by John McDonald Friday, January 14, 2011 3:45 PM
    Friday, January 14, 2011 9:24 AM
  • Olaf,

    Than for the example and good advice - I'm still learning WPF so it makes sense for me to start thinking like WPF instead of Forms 8-)

    John


    John McDonald
    Friday, January 14, 2011 1:49 PM
  • Hi John,

    I know it's hard to dump just about every approach you used to take when shifting over to WPF. But the sooner you do that, the better. That is, if you don't, you'll not be a happy person, promised! ;-)


    Cheers,
    Olaf
    http://blogs.intuidev.com
    Friday, January 14, 2011 1:55 PM
  • Oh, and please don't forget to always flag the reply (or replies) that answer your question as such by clicking the Mark As Answer link for the respective post(s). This way, the question gets "closed" and other people looking for a solution to the same or a similar problem do not have to browse through all replies (see the FAQs ).
    Cheers,
    Olaf
    http://blogs.intuidev.com
    • Marked as answer by John McDonald Friday, January 14, 2011 2:45 PM
    • Unmarked as answer by John McDonald Friday, January 14, 2011 3:45 PM
    Friday, January 14, 2011 2:06 PM
  • Hi John,

    um, I really don't want to be bugging you, but I'd suggest you unmark the previous post and rather mark the one that I'll propose - thank you.


    Cheers,
    Olaf
    http://blogs.intuidev.com
    Friday, January 14, 2011 3:10 PM