I have started the familiarize myself with WPF and have gotten stuck with the ListView

I've read a lot of documentation about binding and I can't seem to find how to populate a ListView programmatically. It seems like a lot of work to create the binding and classes, etc, just to fill a ListView.

So I have 2 questions.
1. If you want to populate a ListView with data that a user has inputted, is the correct way in WPF to populate the ListView with binded data?

2. How do you add items and subitems to a ListView in code? (There doesn't seem to be a subitems in WPF.)

Thanks in advance!

Its actually not much work. Check this example:

The Designer part:

<Window x:Class="MainWindow"
		xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
		xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
		xmlns:local="clr-namespace:WpfApplication1"
		Title="MainWindow"
		Height="400"
		Width="600">
	<Grid>
		<Grid.RowDefinitions>
			<RowDefinition />
			<RowDefinition Height="Auto" />
			<RowDefinition Height="Auto" />
			<RowDefinition Height="Auto" />
		</Grid.RowDefinitions>
		<Grid.Resources>
			<HierarchicalDataTemplate DataType="{x:Type local:Dummy}"
									  ItemsSource="{Binding Path=.}">
				<StackPanel>
					<StackPanel Orientation="Horizontal">
						<TextBlock Text="{Binding Path=ID}" />
						<TextBlock Text=" - " />
						<TextBlock Text="{Binding Path=Name}" />
					</StackPanel>
					<ItemsControl Margin="30,0,0,0"
								  ItemsSource="{Binding Data}" />
				</StackPanel>
			</HierarchicalDataTemplate>
		</Grid.Resources>
		<ListView x:Name="lst" />
		<Button Grid.Row="1"
				Margin="0,10,0,5"
				Content="Add items from code behind"
				Click="ManuallyAdded_Click" />
		<Button Grid.Row="2"
				Margin="0,5,0,10"
				Content="Clear Listview"
				Click="Clear_Click" />
		<Button Grid.Row="3"
				Content="Bind listview to source"
				Click="SourceBinding_Click" />
	</Grid>
</Window>

Code behind:

Imports System.Collections.ObjectModel

Class MainWindow

	Private Sub ManuallyAdded_Click(sender As System.Object, e As System.Windows.RoutedEventArgs)
		ResetItems()
		For i As Integer = 0 To 10
			Dim dum As Dummy = CreateDummy(i)
			GetDummies(dum)
			lst.Items.Add(dum)
		Next
	End Sub

	Private Sub SourceBinding_Click(sender As System.Object, e As System.Windows.RoutedEventArgs)
		Dim source As New List(Of Dummy)
		For i As Integer = 0 To 10
			Dim dum As Dummy = CreateDummy(i)
			GetDummies(dum)
			source.Add(dum)
		Next
		ResetItems()
		lst.ItemsSource = source
	End Sub

	Private Sub Clear_Click(sender As System.Object, e As System.Windows.RoutedEventArgs)
		ResetItems()
	End Sub

	Private Sub GetDummies(parent As Dummy)
		For i As Integer = 0 To 10
			parent.Data.Add(CreateDummy(i))
		Next
	End Sub

	Private Function CreateDummy(i As Integer) As Dummy
		Return New Dummy With {.ID = i, .Name = "Dummy" & i}
	End Function


	Private Sub ResetItems()
		lst.ItemsSource = Nothing
		lst.Items.Clear()
	End Sub
End Class

Public Class Dummy

	Public Property ID() As Integer
	Public Property Name() As String
	Public Property Data() As New ObservableCollection(Of Dummy)

End Class

Hope it helps.

Thanks for the advice, I'm going through it at the moment.

I'm getting an unhandled exception error on the line:
<HierarchicalDataTemplate DataType="{x:Type local:Dummy}"
Error: Type 'local:Dummy' was not found.

I changed the
xmlns:local="clr-namespace:WpfApplication1"
to
xmlns:local="clr-namespace:Hello_World"
but I still get the error.

I'm not sure what I'm missing here, because I do see the class?

After adding the Dummy Class, you have to compile the code. After compiling you can use the {x:Type local:Dummy}
Your application name is "Hello_World" i assume. Then make sure the Dummy class is not in a different namespace. If you in example have the dammy class in namespace "Models" then you have to change xmlns:local="clr-namespace:Hello_World" to xmlns:local="clr-namespace:Hello_World.Models"

If you cant get it to work, then you can attach your project here and i will take a look in it.

Thanks again!

I just had to rebuild :)

I think it's something I'm going to have to get used to with WPF.

I'm going to use your code as a guide and see if I can figure this all out.

Much appreciated!

A quick question. How come the items are not put inside the ListView?

How does WPF know to put the StackPanel and the ItemsControl inside the ListView?

this is defined in the HierarchicalDataTemplate. Means, whenever a item in this window is of type "local:Dummy" then this template will get used.

I'm starting to understand the binding now, thank you. I just don't understand what the point was of MS changing away from the way forms used to work to using binding? It really wasn't that much of a hassle to say Textbox1.Text = Textbox2.Text.

Once you fully understand the binding in WPF you won't waste a single thought on to winforms anymore ;)
The bindings in WPF is so much more powerful and scalable, i won't miss it anymore.

I've just been thinking ahead as to where I'm probably going to struggle with binding.

I'm updating an accounting application at the moment. Where I think I'm going to have the first major issue is in the Invoice screen. What happens is that when the user is in the first column of the datagrid, they input an item code and press Enter. The application then fetches the data and populates some of the other columns in that row with the data. (eg: Description and Selling Price.) The user can then press Enter to get to the quantity and if they update the quantity, the Total Selling Price would need to be updated. It seems that this is going to be tough to do with binding.

Do you have any suggestions as to how to go about doing this?

If you populate your data from a SQL server then i would suggest you to take a look at "LINQ to SQL" or "Entity Framework Models".

Had this project handed over to me, it's using mysql.

Would you suggest using a 3rd party datagrid control?

I've now managed to figure out the populating of the List from your example.

How do I now read those values if I want loop through the List?

For Each item As Dummy In lst.Items
			Debug.WriteLine(item.Name)
		Next

:$ thanks!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.