<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>listview Archive - Robert Skibbe</title>
	<atom:link href="https://robbelroot.de/blog/tag/listview/feed/" rel="self" type="application/rss+xml" />
	<link></link>
	<description>alias RobbelRoot – Freelance Full Stack Developer .NET</description>
	<lastBuildDate>Wed, 25 Mar 2026 12:45:11 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://robbelroot.de/wp-content/uploads/2020/12/cropped-favicon-32x32.png</url>
	<title>listview Archive - Robert Skibbe</title>
	<link></link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>The WPF ListView Control – the complete Guide in 2026</title>
		<link>https://robbelroot.de/blog/the-wpf-listview-control-the-complete-guide/</link>
					<comments>https://robbelroot.de/blog/the-wpf-listview-control-the-complete-guide/#comments</comments>
		
		<dc:creator><![CDATA[Robert Skibbe]]></dc:creator>
		<pubDate>Sun, 08 Jan 2023 22:20:21 +0000</pubDate>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Visual Basic .NET (EN)]]></category>
		<category><![CDATA[basic]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[control]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[foundation]]></category>
		<category><![CDATA[guide]]></category>
		<category><![CDATA[item]]></category>
		<category><![CDATA[items]]></category>
		<category><![CDATA[list]]></category>
		<category><![CDATA[listing]]></category>
		<category><![CDATA[listview]]></category>
		<category><![CDATA[mvvm]]></category>
		<category><![CDATA[presentation]]></category>
		<category><![CDATA[repeat]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[vb]]></category>
		<category><![CDATA[vb.net]]></category>
		<category><![CDATA[vbnet]]></category>
		<category><![CDATA[view]]></category>
		<category><![CDATA[visual]]></category>
		<category><![CDATA[visual basic]]></category>
		<category><![CDATA[windows]]></category>
		<category><![CDATA[wpf]]></category>
		<guid isPermaLink="false">https://robbelroot.de/?p=14035</guid>

					<description><![CDATA[<p>The WPF ListView – listing items / things In today&#8217;s post, we are going to talk about one of the most basic controls: The WPF ListView. We will take a look at the different use cases of the ListView and we will try out some of the architectural styles. As &#8230;</p>
<p>Der Beitrag <a href="https://robbelroot.de/blog/the-wpf-listview-control-the-complete-guide/">The WPF ListView Control – the complete Guide in 2026</a> erschien zuerst auf <a href="https://robbelroot.de">Robert Skibbe</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2023/01/WPF-ListView-Control-the-complete-Guide-640px.png"><img fetchpriority="high" decoding="async" width="640" height="360" src="https://robbelroot.de/wp-content/uploads/2023/01/WPF-ListView-Control-the-complete-Guide-640px.png" alt="WPF ListView Control - the complete Guide" class="wp-image-14042" title="WPF ListView Control - the complete Guide"/></a><figcaption class="wp-element-caption">WPF ListView Control &#8211; the complete Guide</figcaption></figure>






<h2 class="wp-block-heading">The WPF ListView – listing items / things</h2>



<p>In today&#8217;s post, we are going to talk about one of the most basic controls: The WPF ListView. We will take a look at the different use cases of the ListView and we will try out some of the architectural styles. As MVVM is like the &#8222;way to go&#8220; in WPF, I will definitely examine this, but we won&#8217;t forget the &#8222;old way&#8220;. Like always, I will provide different source code examples in the two most used .NET languages, being C# and VB.NET.</p>



<p>This guide and all examples are compatible with .NET 8 and .NET 9.</p>



<p>Speaking of languages: Make sure Visual Studio is set up correctly → <strong><a href="https://robbelroot.de/blog/how-to-change-the-visual-studio-installer-language/" type="post" id="16369">Change VS Installer Language</a></strong>.</p>


<p class="rr-alert info" style="background:#e3f7fc;"><img decoding="async" alt="Info notice" src="https://robbelroot.de/wp-content/themes/pinboard-child/imgs/info.png"><span style="color:black;align-self: center;">Need quick help? Jump to the corresponding sections by using the <a href="#toc_container">table of contents</a>. When you are using the <a href="#code-behind-approach">code behind based approach</a>, jump there. If you are more the MVVM guy, you could jump and start with the <a href="#working-with-real-data">&#8222;MVVM approach&#8220; section</a>.</span></p>



<h2 class="wp-block-heading">What is a WPF ListView?</h2>



<p>When stumbling upon this control, the first question coming to your mind could be: &#8222;Well, what is a ListView – in the Windows Presentation Foundation – in the first place?&#8220;. I mean, by the name, you could just assume, that it&#8217;s something for displaying like a &#8222;list&#8220; of something, right? I mean, you are pretty much on the right side, but what makes it different from like a DataGrid, or even a ListBox? Don&#8217;t worry, we will cover this is a few minutes, further down below.</p>



<h3 class="wp-block-heading">The definition, I guess?</h3>



<p>Let&#8217;s first define, what a ListView really is by like definition:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><em>A WPF ListView provides the basic tools needed, to help you displaying a set of data items. This can be easily done in like different views or layouts, depending on your usecase. Each item of those ListViews are displayed, using something called ListViewItem. A ListViewItem iteself  is – more or less – just another template-ish element, being a ContentControl.</em></p>
</blockquote>



<h3 class="wp-block-heading">Examining the ListView</h3>



<p>Let&#8217;s take a quick sneak peek into the inheritance-tree, of the WPF ListView Control, by pressing F12, while being on one of those with your mouse cursor. There you can see, that it actually inherits from the class ListBox.</p>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2023/01/WPF-ListView-Control-Class-inheriting-from-ListBox.png"><img decoding="async" width="809" height="363" src="https://robbelroot.de/wp-content/uploads/2023/01/WPF-ListView-Control-Class-inheriting-from-ListBox.png" alt="WPF ListView Control Class - inheriting from ListBox" class="wp-image-14056" title="WPF ListView Control Class - inheriting from ListBox"/></a><figcaption class="wp-element-caption">WPF ListView Control Class &#8211; inheriting from ListBox</figcaption></figure>



<h3 class="wp-block-heading">Inheritance tree</h3>



<p>Going further down, there are some other classes in the inheritance tree as well, like the Selector &amp; the ItemsControl class. I think, for most persons, it&#8217;s actually a surprise / a &#8222;good to know&#8220;-thing, that the ListView actually inherits from the ListBox class.</p>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2023/01/WPF-ListView-Inheritance-Tree-640px.png"><img decoding="async" width="640" height="360" src="https://robbelroot.de/wp-content/uploads/2023/01/WPF-ListView-Inheritance-Tree-640px.png" alt="WPF ListView Inheritance Tree" class="wp-image-14088" title="WPF ListView Inheritance Tree"/></a><figcaption class="wp-element-caption">WPF ListView Inheritance Tree</figcaption></figure>



<p>At this point, you can see, that there&#8217;s pretty much going on in the background. The ListView itself is actually derived from a few levels of control hierarchy and is therefore bringing a lot &#8222;to the table&#8220;. For sure, we can&#8217;t go to every level in detail, but I think the most important ones for you are beginning at the ItemsControl.</p>



<p>I mean, in a real application scenario, you would most likely fetch some data like the &#8222;charts&#8220; or something like that. Those could then be displayed inside your ListView by specifying what should actually appear. The chart object could be composed from many different objects and therefore you would need to specify a bit further. </p>



<h2 class="wp-block-heading" id="code-behind-approach">A first example – with XAML &amp; code behind</h2>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2023/01/A-first-WPF-ListView-example-–-hardcoded-in-XAML-640px.png"><img loading="lazy" decoding="async" width="640" height="360" src="https://robbelroot.de/wp-content/uploads/2023/01/A-first-WPF-ListView-example-–-hardcoded-in-XAML-640px.png" alt="A first WPF ListView example – hardcoded in XAML" class="wp-image-14094" title="A first WPF ListView example – hardcoded in XAML"/></a><figcaption class="wp-element-caption">A first WPF ListView example – hardcoded in XAML</figcaption></figure>



<p>Let&#8217;s now focus on creating an actual first example of the ListView Control. To do so, we usually need to first have some kind of data to display. At this point, we will just create some hardcoded items, to see, how the ListView and its ListViewItems are created in the first place. Keep in mind, that we will do this and more in an MVVM manner, later – which is the preferred way for me personally.</p>



<p>We will surround the ListView by a GroupBox Control, to have some kind of labelling, etc. So go ahead and create a GroupBox XAML markup inside your MainWindow.xaml (inside the root Grid). You can write something like &#8222;Music stars&#8220;, etc. inside the Header Property of that GroupBox, like this, we have some kind of heading for our list.</p>



<p>After that, we can add some sort of styling like padding, a width and alignments to that GroupBox, to make it look less bruised. The final, but first testing XAML code could therefore look like this:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">    &lt;Grid>
        &lt;GroupBox Header="Some items" Padding="8" Width="200" VerticalAlignment="Center" HorizontalAlignment="Center">
            &lt;ListView>
                &lt;ListView.Items>
                    &lt;ListViewItem Content="Jimmy Hendrix" />
                    &lt;ListViewItem Content="Michael Jackson" />
                    &lt;ListViewItem Content="The Beatles" />
                &lt;/ListView.Items>
            &lt;/ListView>
        &lt;/GroupBox>
    &lt;/Grid></pre>



<p>The visual representation of that XAML code from above, will just look as simple as this.</p>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2023/01/WPF-ListView-–-Displaying-Music-stars-as-simple-list.png"><img loading="lazy" decoding="async" width="789" height="449" src="https://robbelroot.de/wp-content/uploads/2023/01/WPF-ListView-–-Displaying-Music-stars-as-simple-list.png" alt="ListView – Displaying Music stars as simple list" class="wp-image-14099" title="ListView – Displaying Music stars as simple list"/></a><figcaption class="wp-element-caption">WPF ListView – Displaying Music stars as simple list</figcaption></figure>



<h3 class="wp-block-heading">How to add items to the WPF ListView?</h3>



<p>To add some items to the ListView in a &#8222;code behind&#8220;-manner, we need to specify a usual handler for like the click event, of for example a button. We can then react to that click inside of the handler and actually add a new item to the ListView. Go ahead and add a button inside of your MainWindow (Grid) and specify the &#8222;Click&#8220;-Property.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;Button Click="Button_Click" /></pre>



<p>It will suggest, to create an actual handler, you can confirm this and press F12 while being on the &#8222;Button_Click&#8220; text. After that, it will automatically jump to the corresponding part in your code – the code behind file. Feel free to rename that handler (in XAML &amp; code) to pick a better name, like &#8222;btnAddItem_Click&#8220;.</p>



<p>Inside of the click handler, we need to somehow say: &#8222;Hey, ListView, please remove an item!&#8220;. And we are only able to do so, if we have something to talk to. Currently, the ListView doesn&#8217;t have a name, so you should go back and specify a name for it:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;ListView x:Name="MusicArtistList" ....>
    &lt;!-- .... -->
&lt;/ListView></pre>



<p>The button click handler itself could just look like the following. We are just telling the property of the &#8222;MusicArtistList&#8220;, called &#8222;Items&#8220;: &#8222;Hey, please add another entry to yourself, thanks!&#8220;.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="btn-add-item-code-behind">    private void Button_Click(object sender, RoutedEventArgs e)
    {
        MusicArtistList.Items.Add("Sam Smith");
    }</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="btn-add-item-code-behind">    Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
        MusicArtistList.Items.Add("Sam Smith")
    End Sub</pre>



<h3 class="wp-block-heading">How to remove items from the ListView again?</h3>



<p>If you have followed the above steps to actually add an item inside of our ListView, then you could be ready to remove it again. Keep in mind, that you should have like the click handler ready (by specifying the Buttons click property with like &#8222;btnRemove_Click&#8220;) and that the ListView needs a name. Otherwise, we wouldn&#8217;t be able to target it from the code behind file.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="btn-remove-item-code-behind">    private void btnRemove_Click(object sender, RoutedEventArgs e)
    {
        // this only works that easy due to our current "strings" example
        MusicArtistList.Items.Remove("Sam Smith");
    }</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="btn-remove-item-code-behind">    Private Sub btnRemove_Click(sender As Object, e As RoutedEventArgs)
        ' this only works that easy due to our current "strings" example
        MusicArtistList.Items.Remove("Sam Smith")
    End Sub</pre>



<h3 class="wp-block-heading">How to delete the selected item in the ListView?</h3>



<p>This one here is a bit different, because we can&#8217;t know at compile time, which one of the items, the user will select. We can&#8217;t therefore hardcode like a specific string thing, to be deleted later. We need a possibility, to get the currently selected item and delete it somehow.</p>



<p>This is actually pretty easy, as we get everything we need to know, from the ListView itself. We will first check, if there&#8217;s an actual selection and if so, we will delete that item by providing its index.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="C#" data-enlighter-group="btn-remove-selecteditem-code-behind">    private void btnRemoveSelectedItem_Click(object sender, RoutedEventArgs e)
    {
        bool noItemSelected = MusicArtistList.SelectedIndex == -1;
        if (noItemSelected)
            return;
        MusicArtistList.Items.RemoveAt(MusicArtistList.SelectedIndex);
    }</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="VB.NET" data-enlighter-group="btn-remove-selecteditem-code-behind">Private Sub btnRemoveSelectedItem_Click(sender As Object, e As RoutedEventArgs)
    Dim noItemSelected As Boolean = MusicArtistList.SelectedIndex = -1
    If noItemSelected Then
        Return
    End If
    MusicArtistList.Items.RemoveAt(MusicArtistList.SelectedIndex)
End Sub</pre>



<h3 class="wp-block-heading">Okay, but not flexible, nor practical – imo</h3>



<p>So in the end, we just created a small ListView representation with like 3 entries for our music stars / artists. Currently, this isn&#8217;t really good, as it&#8217;s not dynamic or based on &#8222;real data&#8220;. We just hardcoded those ListViewItems inside the ListView and this isn&#8217;t pretty much practical.</p>



<p>The other problem with our current example is, that it&#8217;s not pretty flexible, currently we are having only like &#8222;1 Column&#8220;. With that, we can only display one &#8222;thing&#8220; per item and we are not really different from a ListBox. What if we wanted to publish some sort of &#8222;year of birth&#8220; information? I mean sure, we could just pump it into one string, but nah, that doesn&#8217;t feel right.</p>



<p>What we really need are some sort of columns and guess what, the ListView supports this out of the box, by just specifying the View property.</p>



<div style="box-sizing:border-box;margin:36px 0;border-radius:12px;overflow:hidden;background:#1a1a2e;position:relative;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
  <div style="position:absolute;inset:0;background-image:linear-gradient(rgba(255,255,255,0.03) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,0.03) 1px,transparent 1px);background-size:40px 40px;pointer-events:none;"></div>
  <div style="position:absolute;top:-60px;right:-60px;width:240px;height:240px;background:radial-gradient(circle,rgba(230,126,34,0.18) 0%,transparent 70%);pointer-events:none;"></div>
  <div style="position:relative;padding:32px 28px;">
    <div style="display:inline-block;font-size:11px;font-weight:700;letter-spacing:2.5px;text-transform:uppercase;color:#e67e22;margin-bottom:14px;border:1px solid rgba(230,126,34,0.35);border-radius:4px;padding:3px 10px;">Need a WPF developer?</div>
    <p style="margin:0 0 10px 0;font-size:clamp(17px,4vw,21px);font-weight:700;color:#ffffff;line-height:1.35;">Got a WPF project that needs professional hands?</p>
    <p style="margin:0 0 24px 0;font-size:14px;color:rgba(255,255,255,0.65);line-height:1.7;max-width:540px;">I build WPF applications with clean MVVM architecture in C# and VB.NET — professionally and efficiently. Just send me a message.</p>
    <div style="display:flex;flex-wrap:wrap;gap:12px;align-items:center;">
      <a href="https://robbelroot.de/contact/" style="display:inline-block;padding:12px 24px;background:#e67e22;color:#ffffff;font-size:14px;font-weight:700;text-decoration:none;border-radius:7px;white-space:nowrap;" onmouseover="this.style.background='#cf6d17'" onmouseout="this.style.background='#e67e22'">→ Get in touch</a>
    </div>
  </div>
</div>



<h2 class="wp-block-heading" id="working-with-real-data">Working with &#8222;real data&#8220; – MVVM approach</h2>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2023/01/Working-with-a-databound-ListView-–-dynamic-data-640px.png"><img loading="lazy" decoding="async" width="640" height="360" src="https://robbelroot.de/wp-content/uploads/2023/01/Working-with-a-databound-ListView-–-dynamic-data-640px.png" alt="Working with a databound ListView – dynamic data" class="wp-image-14110" title="Working with a databound ListView – dynamic data"/></a><figcaption class="wp-element-caption">Working with a databound ListView – dynamic data</figcaption></figure>



<p>Moving away from that unpractical non-databased &#8222;stringish&#8220; approach from above, we will now start a newer, clean version of our ListView Control. But first, we need to actually define &#8222;what&#8220; to display, I mean, we need some sort of a so called &#8222;Model&#8220; (or even a ViewModel – but I&#8217;ll leave it at that for now). As we wanted to display some sort of &#8222;music star&#8220;-overview, we could think of a better term in the first place. I will call it list of artists, so let&#8217;s now <strong>create a new class called &#8222;MusicArtist&#8220;</strong> inside a matching folder.</p>



<p>Go ahead and <strong>create the corresponding folder</strong> inside your WPF project, first. We will call that folder like &#8222;<strong>Models</strong>&#8220; – remember, I don&#8217;t want to go too deep into the MVVM cosmos. I would encourage you to <strong><a href="https://robbelroot.de/blog/mvvm-csharp/" target="_blank" rel="noreferrer noopener">refer to my C# MVVM post</a></strong> for that and don&#8217;t be confused, it will for work VB.NET as well. I mean the characteristics of Model-View-ViewModel are in the focus, not the language itself :).</p>



<h3 class="wp-block-heading">The &#8222;MusicArtist&#8220; model class</h3>



<p>Thinking about the class itself and keeping our example from above in mind, we could say, that a music artist has the following properties. For sure, it&#8217;s just for our example and I&#8217;m trying to stay as easy as possible, so feel free to change anything you would like to.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="MusicArtist.cs" data-enlighter-group="artist-class">using System;

namespace WpfListViewExampleCs.Models;

public class MusicArtist
{

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public DateTime Birthday { get; set; }

    public MusicArtist(string firstName, string lastName, DateTime birthday)
    {
        FirstName = firstName;
        LastName = lastName;
        Birthday = birthday;
    }
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="MusicArtist.vb" data-enlighter-group="artist-class">Imports System

Namespace WpfListViewExampleCs.Models

    Public Class MusicArtist

        Public Property FirstName As String

        Public Property LastName As String

        Public Property Birthday As DateTime

        Public Sub New(firstName As String, lastName As String, birthday As DateTime)
            Me.FirstName = firstName
            Me.LastName = lastName
            Me.Birthday = birthday
        End Sub

    End Class

End Namespace</pre>



<p>In my example here, the music artist has two properties for the name, meaning a first- and a lastname. I don&#8217;t like the &#8222;name&#8220; only approach, as you can&#8217;t easily separate the names in some situations. Well, I mean yeah, before you mention it: &#8222;The Beatles&#8220; isn&#8217;t really nicely separatable in this manner, but, welcome to the world of software development. I would say, this isn&#8217;t the right moment to argue about this, so feel free – again – to change that as you wish. Additionally I thought about using the birthday property, to show some sort of formatting in the XAML as well.</p>



<h2 class="wp-block-heading">Displaying bound data inside the WPF ListView</h2>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2023/01/Displaying-bound-data-inside-the-WPF-ListView-640px.png"><img loading="lazy" decoding="async" width="640" height="360" src="https://robbelroot.de/wp-content/uploads/2023/01/Displaying-bound-data-inside-the-WPF-ListView-640px.png" alt="Displaying bound data inside the ListView" class="wp-image-14135" title="Displaying bound data inside the ListView"/></a><figcaption class="wp-element-caption">Displaying bound data inside the WPF ListView</figcaption></figure>



<p>After specifying some kind of model to actually display inside the ListView, we now go ahead and tell the ListView about its datasource. The ListView will then know: &#8222;Where can I fetch my data from? What is my data?&#8220;.</p>



<h3 class="wp-block-heading">Preventing a known error</h3>



<p>But before, we need to clean up the old code, otherwise we could run into an error like this:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><em>System.InvalidOperationException: &#8222;The items collection must be empty before using itemssource&#8220;</em></p>
</blockquote>



<p>To avoid this error, you need to remove the manually added items inside our XAML code. You can&#8217;t like say: &#8222;Hey, fetch the items from this datasource here&#8220; AND put them in manually by XAML. Please go ahead and remove this marked area from the XAML code:</p>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2023/01/Removing-the-hardcoded-XAML-Items-from-the-ListView.png"><img loading="lazy" decoding="async" width="526" height="201" src="https://robbelroot.de/wp-content/uploads/2023/01/Removing-the-hardcoded-XAML-Items-from-the-ListView.png" alt="Removing the hardcoded XAML Items from the ListView" class="wp-image-14130" title="Removing the hardcoded XAML Items from the ListView"/></a><figcaption class="wp-element-caption">Removing the hardcoded XAML Items from the ListView</figcaption></figure>



<h3 class="wp-block-heading">Giving the ListView its datasource</h3>



<p>In the next step, we will actually care for some items being displayed. For this, we will <strong>use the DataSource property of the ListView</strong> and bind to some property from our ViewModel. Don&#8217;t be scared, if you don&#8217;t know what a ViewModel is! Maybe this is another chance, to refer to <strong><a href="https://robbelroot.de/blog/mvvm-csharp/" target="_blank" rel="noreferrer noopener">my blog post considering the MVVM pattern</a></strong>.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;ListView ItemsSource="{Binding MusicArtists}">
&lt;!-- rest of the listview.. -->
&lt;/ListView></pre>



<p>We won&#8217;t create a separate ViewModel right now, for this simple example, we will use the MainWindow itself. This is pretty much easier at this point and it won&#8217;t push you too far away from the actual topic. Never the less, we still need a bindable property inside our MainWindow, which we are going to create, now.</p>



<h3 class="wp-block-heading">Creating a bindable property</h3>



<p>To create the announced property, just build some normal property inside your MainWindow (for example) called &#8222;MusicArtists&#8220;. This could look like the following code, keep in mind, that we should use something which implements the &#8222;INotifyCollectionChanged&#8220; interface. But yes, I hear you, this should be a topic for another blog post, so just take it like that for now.</p>



<p>Next, create that property called &#8222;MusicArtists&#8220; of type of &#8222;ObservableCollection&#8220;, with the generic type argument &#8222;MusicArtist&#8220;. We could also just make it like readonly, but those are fine tuning things, which aren&#8217;t necessary right now.</p>



<p>The last important step is, to say: &#8222;Hey, MainWindow, your DataContext is actually.. you!&#8220;. Then the MainWindow will know where to find the corresponding &#8222;MusicArtists&#8220;, which we are going to bind very soon from the XAML side. Take a look at the following example XAML code:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="MainWindow.xaml.cs" data-enlighter-group="datasource-init">using System;
using System.Collections.ObjectModel;
using System.Windows;
using WpfListViewExampleCs.Models;

namespace WpfListViewExampleCs;

/// &lt;summary>
/// Interaction logic for MainWindow.xaml
/// &lt;/summary>
public partial class MainWindow : Window
{

    public ObservableCollection&lt;MusicArtist> MusicArtists { get; set; }

    public MainWindow()
    {
        InitializeComponent();
        MusicArtists = new ObservableCollection&lt;MusicArtist>();
        DataContext = this;
    }
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="MainWindow.xaml.vb" data-enlighter-group="datasource-init">Imports System
Imports System.Collections.ObjectModel
Imports System.Windows
Imports WpfListViewExampleCs.Models

Namespace WpfListViewExampleCs

    Public Partial Class MainWindow
        Inherits Window

        Public Property MusicArtists As ObservableCollection(Of MusicArtist)

        Public Sub New()
            InitializeComponent()
            MusicArtists = New ObservableCollection(Of MusicArtist)()
            DataContext = Me
        End Sub

    End Class

End Namespace</pre>



<h3 class="wp-block-heading">Filling up some data</h3>



<p>Currently, the ListView wouldn&#8217;t be able to display much, because there just aren&#8217;t no items inside the &#8222;MusicArtists&#8220;, yet. So in the next step we are going to fill up some items, to make the ListView be able to display those. This is the reason, why we added a quick constructor inside the &#8222;MusicArtist&#8220; class: Creating quick example artists.</p>



<p>Let&#8217;s re-create the MainWindow constructor for this:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="MainWindow.xaml.cs" data-enlighter-group="filling-data">// rest of the MainWindow code behind file

    public MainWindow()
    {
        InitializeComponent();
        MusicArtists = new ObservableCollection&lt;MusicArtist>();
        MusicArtists.Add(new MusicArtist("Jimmy", "Hendrix", new DateTime(1942, 11, 27)));
        MusicArtists.Add(new MusicArtist("Michael", "Jackson", new DateTime(1958, 8, 29)));
        MusicArtists.Add(new MusicArtist("The", "Beatles", new DateTime(1960, 1, 1)));
        DataContext = this;
    }

// rest of the MainWindow code behind file</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="MainWindow.xaml.vb" data-enlighter-group="filling-data">' rest of the MainWindow code behind file

Public Sub New()
    InitializeComponent()
    MusicArtists = New ObservableCollection(Of MusicArtist)()
    MusicArtists.Add(New MusicArtist("Jimmy", "Hendrix", New DateTime(1942, 11, 27)))
    MusicArtists.Add(New MusicArtist("Michael", "Jackson", New DateTime(1958, 8, 29)))
    MusicArtists.Add(New MusicArtist("The", "Beatles", New DateTime(1960, 1, 1)))
    DataContext = Me
End Sub

' rest of the MainWindow code behind file</pre>



<h3 class="wp-block-heading">But it&#8217;s displaying rubbish now?</h3>



<p>If you are looking at the current results, you would pretty much only see rubbish. If you didn&#8217;t look until now, please watch the following screenshot, then you probably will. The items are more or less being displayed, but there&#8217;s only something like &#8222;Blabla.Bla.MusicArtist&#8220; written.</p>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2023/01/Bound-ListView-Items-without-Column-Bindings-1.png"><img loading="lazy" decoding="async" width="454" height="178" src="https://robbelroot.de/wp-content/uploads/2023/01/Bound-ListView-Items-without-Column-Bindings-1.png" alt="Bound ListView Items displaying rubbish without Column Bindings" class="wp-image-14159" title="Bound ListView Items displaying rubbish without Column Bindings"/></a><figcaption class="wp-element-caption">Bound ListView Items displaying rubbish without Column Bindings</figcaption></figure>



<p>The reason for that is, that the corresponding ListViewItem actually knows: &#8222;Hey, there is something called MusicArtist&#8220;. But it&#8217;s also asking itself: &#8222;well, how am I supposed to display this? Property A, B, C, WHAT!?&#8220;. In the end it thinks: &#8222;You know what, dev? I&#8217;m just going to display THAT over here&#8220;.</p>



<p>By &#8222;that&#8220; I&#8217;m meaning the complete path to the corresponding class instance type. We are having a class called &#8222;MusicArtist&#8220; inside our project called &#8222;WpfListViewExampleCs&#8220; AND inside the &#8222;Models&#8220; namespace. So this is basically why that &#8222;rubbish&#8220; comes out of it, it displays the complete namespace to class path!</p>



<h3 class="wp-block-heading">Overriding that &#8222;default-rubbish&#8220;</h3>



<p>Before we are going to use the final solution for this, I first want to explain and show you, how you could potentially solve it at this point. Please keep in mind, that this solution depends on your usecase! Usually, if you want to display like &#8222;multiple columns&#8220;, you would actually need – well – multiple columns.</p>



<p>In the image from above, you are seeing the <strong><a href="https://learn.microsoft.com/en-us/dotnet/api/system.object.tostring?view=net-9.0" target="_blank" rel="noreferrer noopener">default object class &#8222;ToString&#8220;</a></strong> output. To change it, you can just override it in your derived class – being the &#8222;MusicArtist&#8220;-class like in a second. Hint: I&#8217;m using the newer, shorter version of the overriding functionality. This means, no body parantheses and an arrow (for C#), as well as string interpolation (for both languages).</p>



<p>You could add this to the &#8222;MusicArtist&#8220; class:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="MusicArtist.cs" data-enlighter-group="override-musicartist-tostring">// rest of the MusicArtist class

public override string ToString()
    => $"{FirstName} {LastName}";

// rest of the MusicArtist class</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="MusicArtist.vb" data-enlighter-group="override-musicartist-tostring">' rest of the MusicArtist class

Public Overrides Function ToString() As String
    Return $"{FirstName} {LastName}"
End Function

' rest of the MusicArtist class</pre>



<p>So the current / new output would look like this:</p>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2023/01/Bound-ListView-Items-with-overriden-ToString-Function.png"><img loading="lazy" decoding="async" width="354" height="210" src="https://robbelroot.de/wp-content/uploads/2023/01/Bound-ListView-Items-with-overriden-ToString-Function.png" alt="Bound ListView Items with overriden ToString Function" class="wp-image-14168" title="Bound ListView Items with overriden ToString Function"/></a><figcaption class="wp-element-caption">Bound ListView Items with overriden ToString Function</figcaption></figure>



<h2 class="wp-block-heading">Using the ListViews &#8222;View&#8220; Property creating columns</h2>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2023/01/Creating-columns-using-the-ListView-View-Property-640px.png"><img loading="lazy" decoding="async" width="640" height="360" src="https://robbelroot.de/wp-content/uploads/2023/01/Creating-columns-using-the-ListView-View-Property-640px.png" alt="Creating columns using the ListView View Property" class="wp-image-14218" title="Creating columns using the ListView View Property"/></a><figcaption class="wp-element-caption">Creating columns using the ListView View Property</figcaption></figure>



<p>After cleaning up that &#8222;namespace and class&#8220;-mess we saw in the last section, we now can go the last step (I think). Currently, our ListView is only displaying some kind of single dimensioned data, which is not thaaaat bad, but I guess bad for multi-dimensioned data? What if I wanted to have some sort of separated columns for first and last name? This is exactly, where the so called &#8222;View&#8220;-property of the WPF ListView comes into play!</p>



<h3 class="wp-block-heading">But why a ListView, why no DataGrid instead?</h3>



<p>Sure, you could ask yourself: &#8222;Why would I use a ListView, when I could use a DataGrid instead?&#8220;. The answer is: &#8222;It depends&#8220;, yeah, I hate those answers as well.. Usually there&#8217;s one rule floating around in the internet: Use a DataGrid, if you need editing, use a ListView otherwise – bang. I would pretty much love going deeper into this topic, but well, I think this post is already too big, isn&#8217;t it?</p>



<h3 class="wp-block-heading">Specifying a &#8222;View&#8220;-template</h3>



<p>To start creating those columns we talked about, we need to specify some sort of template for the View property. But it&#8217;s not a usual &#8222;DataTemplate&#8220;, it&#8217;s something more special, lemme give you an example. The basic view provided from WPF itself, is something called a &#8222;GridView&#8220;. I mean, the name pretty much suggests what it is. If needed, you could create something similiar for your own needs, but again, I think this would blow up this post even more..</p>



<div style="box-sizing:border-box;margin:36px 0;border-radius:12px;overflow:hidden;background:#1a1a2e;position:relative;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
  <div style="position:absolute;inset:0;background-image:linear-gradient(rgba(255,255,255,0.03) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,0.03) 1px,transparent 1px);background-size:40px 40px;pointer-events:none;"></div>
  <div style="position:absolute;top:-60px;right:-60px;width:240px;height:240px;background:radial-gradient(circle,rgba(230,126,34,0.18) 0%,transparent 70%);pointer-events:none;"></div>
  <div style="position:relative;padding:32px 28px;">
    <div style="display:inline-block;font-size:11px;font-weight:700;letter-spacing:2.5px;text-transform:uppercase;color:#e67e22;margin-bottom:14px;border:1px solid rgba(230,126,34,0.35);border-radius:4px;padding:3px 10px;">Need a WPF developer?</div>
    <p style="margin:0 0 10px 0;font-size:clamp(17px,4vw,21px);font-weight:700;color:#ffffff;line-height:1.35;">Got a WPF project that needs professional hands?</p>
    <p style="margin:0 0 24px 0;font-size:14px;color:rgba(255,255,255,0.65);line-height:1.7;max-width:540px;">I build WPF applications with clean MVVM architecture in C# and VB.NET — professionally and efficiently. Just send me a message.</p>
    <div style="display:flex;flex-wrap:wrap;gap:12px;align-items:center;">
      <a href="https://robbelroot.de/contact/" style="display:inline-block;padding:12px 24px;background:#e67e22;color:#ffffff;font-size:14px;font-weight:700;text-decoration:none;border-radius:7px;white-space:nowrap;" onmouseover="this.style.background='#cf6d17'" onmouseout="this.style.background='#e67e22'">→ Get in touch</a>
    </div>
  </div>
</div>



<p>So let&#8217;s stick with the basic GridView for now. Back into your MVVM prepared ListView, we can now provide a GridView template for our ListView. Watch out for that nice string format functionality, where I specified a custom format for that birthday binding. Basically all you have to do is, providing the columns you want, with a header of your choice. Then you need to tell the ListViewItem, where it should pull the data from (being the DisplayMemberPath-Binding).</p>



<pre class="EnlighterJSRAW" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">            &lt;ListView ItemsSource="{Binding MusicArtists}">
                &lt;ListView.View>
                    &lt;GridView>
                        &lt;GridView.Columns>
                            &lt;GridViewColumn Header="FirstName" DisplayMemberBinding="{Binding FirstName}" />
                            &lt;GridViewColumn Header="LastName" DisplayMemberBinding="{Binding LastName}" />
                            &lt;GridViewColumn Header="Birthday" DisplayMemberBinding="{Binding Birthday, StringFormat={}{0:dd.MM.yyyy}}" />
                        &lt;/GridView.Columns>
                    &lt;/GridView>
                &lt;/ListView.View>
            &lt;/ListView></pre>



<p>And finally, you end up having this nice thing here:</p>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2023/01/WPF-ListView-with-specified-View-Property-as-GridView.png"><img loading="lazy" decoding="async" width="505" height="268" src="https://robbelroot.de/wp-content/uploads/2023/01/WPF-ListView-with-specified-View-Property-as-GridView.png" alt="WPF ListView with specified View Property as GridView" class="wp-image-14226" title="WPF ListView with specified View Property as GridView"/></a><figcaption class="wp-element-caption">WPF ListView with specified View Property as GridView</figcaption></figure>



<h3 class="wp-block-heading">Adding, removing, etc. the MVVM way – preparations</h3>



<p>Because it&#8217;s a bit harder, I saved this topic (and other) for the end of this blog post. You actually need some sort of &#8222;ICommand&#8220; implementation, which we won&#8217;t cover here, but I will give you the example code needed. There will be another blog post about those commands in english, currently, it&#8217;s only available in german, sorry.</p>



<h3 class="wp-block-heading">A DelegateCommand base class</h3>



<p>Please go ahead and <strong>create another folder inside your project</strong>, called &#8222;<strong>Utils</strong>&#8222;. We will deposit a small class over there, which helps us with the buttons in MVVM style. The class I&#8217;m talking about looks like this, it&#8217;s a basic implementation of a delegated action (with check) for the <strong><a href="https://learn.microsoft.com/en-US/dotnet/api/system.windows.input.icommand?view=net-9.0" target="_blank" rel="noreferrer noopener">ICommand-interface</a></strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="DelegateCommand.cs" data-enlighter-group="delegate-command">using System.Windows.Input;
using System;

namespace Utils
{
    public class DelegateCommand : ICommand
    {
        private Action&lt;object?> _action;

        private Func&lt;object?, bool>? _canExecute;

        public DelegateCommand(Action&lt;object?> action)
        {
            _action = action;
        }

        public DelegateCommand(Action&lt;object?> action, Func&lt;object?, bool> canExecute)
        {
            _action = action;
            _canExecute = canExecute;
        }

        public void Execute(object? parameter)
        {
            _action(parameter);
        }

        public bool CanExecute(object? parameter)
        {
            if (_canExecute == null)
                return true;
            return _canExecute(parameter);
        }

        public void RaiseCanExecuteChanged()
        {
            CanExecuteChanged?.Invoke(this, EventArgs.Empty);
        }

        public event EventHandler? CanExecuteChanged;
    }
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="DelegateCommand.vb" data-enlighter-group="delegate-command">Namespace Utils
    Public Class DelegateCommand
        Implements ICommand
        Private _action As Action(Of Object)
        Private _canExecute As Func(Of Object, Boolean)
        Sub New(action As Action(Of Object))
            _action = action
        End Sub
        Sub New(action As Action(Of Object), canExecute As Func(Of Object, Boolean))
            _action = action
            _canExecute = canExecute
        End Sub
        Public Sub Execute(parameter As Object) Implements ICommand.Execute
            ' führt unsere von außen mitgegebene Aktion aus und übergibt auch den Parameter
            _action(parameter)
        End Sub
        Public Function CanExecute(parameter As Object) As Boolean Implements ICommand.CanExecute
            If _canExecute Is Nothing Then
                Return True
            End If
            Return _canExecute(parameter)
        End Function
        Public Event CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged
    End Class
End Namespace</pre>



<h3 class="wp-block-heading">A PropertyChangedBase class</h3>



<p>Without going into too much detail, please copy this class and put it into the &#8222;Utils&#8220; folder as well. There is <strong><a href="https://robbelroot.de/blog/der-ultimative-inotifypropertychanged-guide/" target="_blank" rel="noreferrer noopener">a blog post for the INotifyPropertyChanged-interface</a></strong>, but <strong>currently it&#8217;s only in german</strong>. Maybe you could use a browser-translator for now, but I will add the english version soon. So now, please take this class:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="PropertyChangedBase.cs" data-enlighter-group="property-changed-base">using System.Runtime.CompilerServices;
using System.ComponentModel;

namespace Utils;

public abstract class PropertyChangedBase : INotifyPropertyChanged
{
    protected void NotifyOfPropertyChange([CallerMemberName] string? propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    public event PropertyChangedEventHandler? PropertyChanged;
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="PropertyChangedBase.vb" data-enlighter-group="property-changed-base">Imports System.ComponentModel
Imports System.Runtime.CompilerServices

Namespace Utils

    Public Class PropertyChangedBase
        Implements INotifyPropertyChanged

        Protected Sub NotifyOfPropertyChange(&lt;CallerMemberName> Optional propertyName As String = Nothing)
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
        End Sub

        Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

    End Class

End Namespace</pre>



<h3 class="wp-block-heading">Corresponding buttons</h3>



<p>Please add something like a StackPanel and 3 Buttons inside of it. There will be one button for adding and one for removing an item at a specific position. The third button will be for removing the selected item. At this point, we will also those commands, please have a look at the following XAML. Please pardon me for not making this visually appealing, it&#8217;s only for its functional purpose.</p>



<p>Keep in mind, that you also need to create 3 new properties of type of &#8222;DelegateCommand&#8220;, 1 for each command, being:</p>



<ul class="wp-block-list">
<li>AddItemCommand</li>



<li>RemoveItemCommand</li>



<li>RemoveItemAtIndexCommand</li>
</ul>



<pre class="EnlighterJSRAW" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">        &lt;GroupBox Header="Music stars" Padding="8" Width="400" VerticalAlignment="Center" HorizontalAlignment="Center">
            &lt;StackPanel>
                &lt;ListView SelectedItem="{Binding SelectedMusicArtist}" ItemsSource="{Binding MusicArtists}">
                    &lt;ListView.View>
                        &lt;GridView>
                            &lt;GridView.Columns>
                                &lt;GridViewColumn Header="FirstName" DisplayMemberBinding="{Binding FirstName}" />
                                &lt;GridViewColumn Header="LastName" DisplayMemberBinding="{Binding LastName}" />
                                &lt;GridViewColumn Header="Birthday" DisplayMemberBinding="{Binding Birthday, StringFormat={}{0:dd.MM.yyyy}}" />
                            &lt;/GridView.Columns>
                        &lt;/GridView>
                    &lt;/ListView.View>
                &lt;/ListView>
                &lt;StackPanel Orientation="Horizontal" Margin="0 12 0 0" HorizontalAlignment="Right">
                    &lt;Button Command="{Binding AddItemCommand}" Content="Add item" Margin="0 0 8 0" />
                    &lt;Button Command="{Binding RemoveItemCommand}" Content="Remove item" Margin="0 0 8 0" />
                    &lt;Button Command="{Binding RemoveItemAtIndexCommand}" Content="Remove item at index" />
                &lt;/StackPanel>
            &lt;/StackPanel>
        &lt;/GroupBox></pre>



<p>The &#8222;new&#8220; UI now looks like this:</p>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2023/01/WPF-ListView-MVVM-based-UI-1.png"><img loading="lazy" decoding="async" width="477" height="250" src="https://robbelroot.de/wp-content/uploads/2023/01/WPF-ListView-MVVM-based-UI-1.png" alt="MVVM based UI" class="wp-image-14269" title="MVVM based UI"/></a><figcaption class="wp-element-caption">MVVM based UI</figcaption></figure>



<h3 class="wp-block-heading">The MainViewModel</h3>



<p>Now create a new folder called &#8222;ViewModels&#8220; and a &#8222;MainViewModel&#8220; class inside. Let the &#8222;MainViewModel&#8220; class inherit from the &#8222;PropertyChangedBase&#8220; you copied from the previous paragraph. The view (code behind) file should now be abandoned as it&#8217;s getting too much otherwise.</p>



<p>Over here we fully implemented the &#8222;SelectedMusicArtist&#8220;-property to actually tell the &#8222;RemoveItemCommand&#8220;: &#8222;Hey, here was something selected, check if you can be executed now&#8220;. We&#8217;re  subscribing to the &#8222;CollectionChanged&#8220; event of the ObservableCollection as well. This way, we can also refresh the commands state, when the collection is changed.</p>



<p>In the next steps, we are going to instantiate the commands and therefore telling them, what to do and when.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="MainViewModel.cs" data-enlighter-group="the-main-view-model">using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using Utils;
using WpfListViewExampleCs.Models;

namespace WpfListViewExampleCs.ViewModels;

public class MainViewModel : PropertyChangedBase
{

    public ObservableCollection&lt;MusicArtist> MusicArtists { get; set; }

    private MusicArtist? _selectedMusicArtist;

    public MusicArtist? SelectedMusicArtist
    {
        get => _selectedMusicArtist;
        set
        {
            if (_selectedMusicArtist == value)
                return;
            _selectedMusicArtist = value;
            RemoveItemCommand.RaiseCanExecuteChanged();
        }
    }

    public DelegateCommand AddItemCommand { get; set; }

    public DelegateCommand RemoveItemCommand { get; set; }

    public DelegateCommand RemoveItemAtIndexCommand { get; set; }

    public MainViewModel()
    {
        MusicArtists = new ObservableCollection&lt;MusicArtist>();
        MusicArtists.CollectionChanged += MusicArtists_CollectionChanged;
        MusicArtists.Add(new MusicArtist("Jimmy", "Hendrix", new DateTime(1942, 11, 27)));
        MusicArtists.Add(new MusicArtist("Michael", "Jackson", new DateTime(1958, 8, 29)));
        MusicArtists.Add(new MusicArtist("The", "Beatles", new DateTime(1960, 1, 1)));
    }

    private void MusicArtists_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
    {
        RemoveItemCommand.RaiseCanExecuteChanged();
        RemoveItemAtIndexCommand.RaiseCanExecuteChanged();
    }

}
</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="MainWindow.xaml.vb" data-enlighter-group="the-main-view-model">Imports System
Imports System.Collections.ObjectModel
Imports System.Collections.Specialized
Imports Utils
Imports WpfListViewExampleCs.Models

Namespace WpfListViewExampleCs.ViewModels

    Public Class MainViewModel
        Inherits PropertyChangedBase

        Public Property MusicArtists As ObservableCollection(Of MusicArtist)

        Private _selectedMusicArtist As MusicArtist?

        Public Property SelectedMusicArtist As MusicArtist?
            Get
                Return _selectedMusicArtist
            End Get
            Set(ByVal value As MusicArtist?)
                If _selectedMusicArtist = value Then Return
                _selectedMusicArtist = value
                RemoveItemCommand.RaiseCanExecuteChanged()
            End Set
        End Property

        Public Property AddItemCommand As DelegateCommand

        Public Property RemoveItemCommand As DelegateCommand

        Public Property RemoveItemAtIndexCommand As DelegateCommand

        Public Sub New()
            MusicArtists = New ObservableCollection(Of MusicArtist)()
            AddHandler MusicArtists.CollectionChanged, AddressOf MusicArtists_CollectionChanged
            MusicArtists.Add(New MusicArtist("Jimmy", "Hendrix", New DateTime(1942, 11, 27)))
            MusicArtists.Add(New MusicArtist("Michael", "Jackson", New DateTime(1958, 8, 29)))
            MusicArtists.Add(New MusicArtist("The", "Beatles", New DateTime(1960, 1, 1)))
        End Sub

        Private Sub MusicArtists_CollectionChanged(ByVal sender As Object?, ByVal e As NotifyCollectionChangedEventArgs)
            RemoveItemCommand.RaiseCanExecuteChanged()
            RemoveItemAtIndexCommand.RaiseCanExecuteChanged()
        End Sub

    End Class

End Namespace</pre>



<h3 class="wp-block-heading">Modern alternative (.NET 6+): CommunityToolkit.Mvvm</h3>



<p>Writing <code>DelegateCommand</code> and <code>PropertyChangedBase</code> manually works perfectly fine &#x1f449; and understanding how they work is exactly why we did it this way. But in 2026, you would typically reach for the <strong><a href="https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/" target="_blank" rel="noreferrer noopener">CommunityToolkit.Mvvm</a></strong> NuGet package instead.</p>



<p>It ships source generators like <code>[ObservableProperty]</code> and <code>[RelayCommand]</code>, which produce the same boilerplate automatically at compile time, meaning less code to write and maintain.</p>



<p>Compare the two approaches with these small code snippets:</p>



<p>&#x274c; Manual (what we did above)</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">private MusicArtist? _selectedMusicArtist;
public MusicArtist? SelectedMusicArtist {
    get => _selectedMusicArtist;
    set { _selectedMusicArtist = value; NotifyOfPropertyChange(); }
}</pre>



<p>&#x2705; CommunityToolkit.Mvvm</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[ObservableProperty]
private MusicArtist? _selectedMusicArtist;</pre>



<p>Well worth a look once you are comfortable with the concepts above!</p>



<h3 class="wp-block-heading">Assign a ViewModel to the MainWindow</h3>



<p>To be able to this all work, make sure, you set an appropriate ViewModel for your MainWindow. Otherwise, the binding system wouldn&#8217;t know, where to search for your bindings. This is done by adding this code to your MainWindow XAML file:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;!-- create a namespace mapping at the top of your file -->
xmlns:vm="clr-namespace:WpfListViewExampleCs.ViewModels"

&lt;!-- Set the DataContext MainViewModel instance by XAML -->
&lt;Window.DataContext>
    &lt;vm:MainViewModel />
&lt;/Window.DataContext></pre>



<h3 class="wp-block-heading">How to add WPF ListView items with MVVM</h3>



<p>After you got our little helper class from above inside your &#8222;Utils&#8220; folder and everything else ready, we can now continue. Adding items is now kinda different, because our items are actually bound and not just simple strings. Our commands wants at least to know, what it should do, when executed. We can pass a function, to let the command determine, if it can be executed. I mean, we don&#8217;t want a &#8222;remove selected item&#8220; to happen, when there&#8217;s no item, right?</p>



<p>The following code is needed for the actual functionality: Instantiate the command inside the constructor (don&#8217;t forget to take the command property from above!).</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="MainViewModel.cs" data-enlighter-group="main-view-model-add-item">    // other properties

    public DelegateCommand AddItemCommand { get; set; }

    public MainViewModel()
    {
        AddItemCommand = new DelegateCommand(AddItem);

        // list instantiation etc..
    }

    // the delegate function to be executed on click
    private void AddItem(object? parameter)
    {
        // adding miley cyrus, as we have no dynamic dialog, as it's not a part of this here..
        MusicArtists.Add(new MusicArtist("Miley", "Cyrus", new DateTime(1992, 11, 23)));
    }</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="MainViewModel.vb" data-enlighter-group="main-view-model-add-item">    ' other properties
   
    Public Property AddItemCommand As DelegateCommand

    Sub New()
        AddItemCommand = new DelegateCommand(AddItem);

        ' list instantiation etc..
    End Sub

    Private Sub AddItem(parameter As Object)
        MusicArtists.Add(New MusicArtist("Miley", "Cyrus", New DateTime(1992, 11, 23)))
    End Sub</pre>



<h3 class="wp-block-heading">Removing the selected item MVVM style</h3>



<p>The important thing here is, that we can only remove a selected item, if there is actually one selected. Please check the &#8222;SelectedMusicArtist&#8220;-property from the above MainViewModel for this. If the selected item (therefore the SelectedMusicArtist) changes, we tell the command to refresh.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="MainViewModel.cs" data-enlighter-group="main-view-model-remove-item">    // other properties

    public DelegateCommand RemoveItemCommand { get; set; }

    public MainViewModel()
    {
        RemoveItemCommand = new DelegateCommand(RemoveItem, CanRemoveItem);

        // list instantiation etc..
    }

    private void RemoveItem(object? parameter)
    {
        // we should know that SelectedMusicArtist isn't null, therefore the !
        MusicArtists.Remove(SelectedMusicArtist!);
    }

    private bool CanRemoveItem(object? parameter)
    {
        return SelectedMusicArtist != null;
    }</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="MainViewModel.vb" data-enlighter-group="main-view-model-remove-item">    ' other properties
   
    Public Property RemoveItemCommand As DelegateCommand

    Sub New()
        RemoveItemCommand = new DelegateCommand(RemoveItem, CanRemoveItem);

        ' list instantiation etc..
    End Sub

    Private Sub RemoveItem(parameter As Object)
        MusicArtists.Remove(SelectedMusicArtist)
    End Sub

    Private Function CanRemoveItem(parameter As Object) As Boolean
        Return SelectedMusicArtist IsNot Nothing
    End Function</pre>



<h3 class="wp-block-heading">Deleting an item by index, MVVM like</h3>



<p>In the last example, we do pretty much the same, but with some hardcoded index, just as an example!</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="MainViewModel.cs" data-enlighter-group="main-view-model-remove-item-index">    // other properties

    public DelegateCommand RemoveItemAtIndexCommand { get; set; }

    public MainViewModel()
    {
        RemoveItemAtIndexCommand = new DelegateCommand(RemoveItemAtIndex, CanRemoveItemAtIndex);

        // list instantiation etc..
    }

    private void RemoveItemAtIndex(object? parameter)
    {
        // we need at least one item inside
        MusicArtists.RemoveAt(0);
    }

    private bool CanRemoveItemAtIndex(object? parameter)
    {
        return MusicArtists.Count > 0;
    }</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="MainViewModel.vb" data-enlighter-group="main-view-model-remove-item-index">    ' other properties
   
    Public Property RemoveItemAtIndexCommand As DelegateCommand

    Sub New()
        RemoveItemAtIndexCommand = new DelegateCommand(RemoveItemAtIndex, CanRemoveItemAtIndex);

        ' list instantiation etc..
    End Sub

    Private Sub RemoveItemAtIndex(parameter As Object)
        MusicArtists.RemoveAt(0)
    End Sub

    Private Function CanRemoveItemAtIndex(parameter As Object) As Boolean
        MusicArtists.Count > 0
    End Function</pre>



<h2 class="wp-block-heading">Conclusion – WPF ListView Control</h2>



<p>If you want to have a control, which is able to display things in like a list, being able to select one or more items out of it, the ListView is possibly your choice. When thinking about: &#8222;Should I use a ListView or a DataGrid&#8220;, you should choose the ListView, if editing is not a concern. As mostly always, you have the option to go for the code behind, or the MVVM approach, I would personally always choose the MVVM one. It seems much cleaner for my personal preferences and doesn&#8217;t mix up UI with business code. Feel free to leave any comment on how to improve this article, or if I may explained something wrong.</p>



<div style="box-sizing:border-box;margin:36px 0;border-radius:12px;overflow:hidden;background:#1a1a2e;position:relative;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
  <div style="position:absolute;inset:0;background-image:linear-gradient(rgba(255,255,255,0.03) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,0.03) 1px,transparent 1px);background-size:40px 40px;pointer-events:none;"></div>
  <div style="position:absolute;top:-60px;right:-60px;width:240px;height:240px;background:radial-gradient(circle,rgba(230,126,34,0.18) 0%,transparent 70%);pointer-events:none;"></div>
  <div style="position:relative;padding:32px 28px;">
    <div style="display:inline-block;font-size:11px;font-weight:700;letter-spacing:2.5px;text-transform:uppercase;color:#e67e22;margin-bottom:14px;border:1px solid rgba(230,126,34,0.35);border-radius:4px;padding:3px 10px;">Need a WPF developer?</div>
    <p style="margin:0 0 10px 0;font-size:clamp(17px,4vw,21px);font-weight:700;color:#ffffff;line-height:1.35;">Got a WPF project that needs professional hands?</p>
    <p style="margin:0 0 24px 0;font-size:14px;color:rgba(255,255,255,0.65);line-height:1.7;max-width:540px;">I build WPF applications with clean MVVM architecture in C# and VB.NET — professionally and efficiently. Just send me a message.</p>
    <div style="display:flex;flex-wrap:wrap;gap:12px;align-items:center;">
      <a href="https://robbelroot.de/contact/" style="display:inline-block;padding:12px 24px;background:#e67e22;color:#ffffff;font-size:14px;font-weight:700;text-decoration:none;border-radius:7px;white-space:nowrap;" onmouseover="this.style.background='#cf6d17'" onmouseout="this.style.background='#e67e22'">→ Get in touch</a>
    </div>
  </div>
</div>



<h2 class="wp-block-heading">FAQ</h2>



<div class="schema-faq wp-block-yoast-faq-block"><div class="schema-faq-section" id="faq-question-1774441748497"><strong class="schema-faq-question">What is the difference between a WPF ListView and a DataGrid?</strong> <p class="schema-faq-answer">A ListView is best for displaying read-only data in list or grid format, while a DataGrid supports inline editing, sorting, and cell-level interaction. Use a ListView when you only need to display and select items, use a DataGrid when users need to edit data directly in the table.</p> </div> <div class="schema-faq-section" id="faq-question-1774441768936"><strong class="schema-faq-question">How do I add columns to a WPF ListView?</strong> <p class="schema-faq-answer">Set the ListView&#8217;s View property to a GridView, then define GridViewColumn elements with Header and DisplayMemberBinding. Each column binds to a property of your data model, allowing multi-column display.</p> </div> <div class="schema-faq-section" id="faq-question-1774441780175"><strong class="schema-faq-question">Can I use the WPF ListView with MVVM and data binding?</strong> <p class="schema-faq-answer">Yes, bind the ItemsSource property to an ObservableCollection in your ViewModel. Use ICommand implementations (like DelegateCommand or RelayCommand) for add/remove operations, and bind SelectedItem for selection tracking.</p> </div> </div>



<h2 class="wp-block-heading">Downloads</h2>



<p>If you need quick and ready to use examples, just go ahead and download the ones you need. Maybe I&#8217;ll add some more later.</p>



<div class="wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex">
<div class="wp-block-button"><a class="wp-block-button__link wp-element-button" href="https://robbelroot.de/file-download/?dlid=6a6afb78-5d9f-4104-98af-8b46cdb3b68a" target="_blank" rel="noreferrer noopener">WpfListViewExampleCs.zip</a></div>



<div class="wp-block-button"><a class="wp-block-button__link wp-element-button" href="https://robbelroot.de/file-download/?dlid=eae7bc5f-d92c-4b01-b60d-c4e4e362e055" target="_blank" rel="noreferrer noopener">WpfListViewExampleCsMvvm.zip</a></div>
</div>
<p>Der Beitrag <a href="https://robbelroot.de/blog/the-wpf-listview-control-the-complete-guide/">The WPF ListView Control – the complete Guide in 2026</a> erschien zuerst auf <a href="https://robbelroot.de">Robert Skibbe</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://robbelroot.de/blog/the-wpf-listview-control-the-complete-guide/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>FTP String Download in ListView</title>
		<link>https://robbelroot.de/blog/ftp-string-download-in-listview/</link>
					<comments>https://robbelroot.de/blog/ftp-string-download-in-listview/#respond</comments>
		
		<dc:creator><![CDATA[Robert Skibbe]]></dc:creator>
		<pubDate>Sun, 07 Feb 2016 19:51:03 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Visual Basic .NET]]></category>
		<category><![CDATA[Visual Basic .NET Problemlösungen]]></category>
		<category><![CDATA[display]]></category>
		<category><![CDATA[download]]></category>
		<category><![CDATA[ftp]]></category>
		<category><![CDATA[listview]]></category>
		<category><![CDATA[show]]></category>
		<category><![CDATA[string]]></category>
		<category><![CDATA[text]]></category>
		<category><![CDATA[vb]]></category>
		<category><![CDATA[vbnet]]></category>
		<category><![CDATA[visual basic]]></category>
		<guid isPermaLink="false">http://robbelroot.de/?p=857</guid>

					<description><![CDATA[<p>Auf YouTube ansehen Code Download</p>
<p>Der Beitrag <a href="https://robbelroot.de/blog/ftp-string-download-in-listview/">FTP String Download in ListView</a> erschien zuerst auf <a href="https://robbelroot.de">Robert Skibbe</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><script src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js" async=""></script><!-- robbelroot.de pre content --><ins class="adsbygoogle" style="display: inline-block; width: 468px; height: 60px;" data-ad-client="ca-pub-3635281460831831" data-ad-slot="4378945418"></ins><script>// <![CDATA[
(adsbygoogle = window.adsbygoogle || []).push({});
// ]]&gt;</script></p>
<p style="margin-bottom:0;">
<a class="fasc-button fasc-size-medium fasc-type-glossy fasc-rounded-medium fasc-ico-before dashicons-format-video" style="background-color: #ff0000; color: #ffffff;" href="https://www.youtube.com/watch?v=8m3nZ-3Y-A4" target="_blank" data-fasc-style="background-color:#ff0000;color:#ffffff;">Auf YouTube ansehen</a> <a class="fasc-button fasc-size-medium fasc-type-glossy fasc-rounded-medium fasc-ico-before dashicons-download" style="background-color: #339e48; color: #ffffff;" href="https://adf.ly/qyAC4" target="_blank" data-fasc-style="background-color:#339e48;color:#ffffff;">Code Download</a>
</p>
<p><iframe loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/8m3nZ-3Y-A4" frameborder="0" allowfullscreen></iframe></p>
<p><script src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js" async=""></script><!-- robbelroot.de pre content --><ins class="adsbygoogle" style="display: inline-block; width: 468px; height: 60px;" data-ad-client="ca-pub-3635281460831831" data-ad-slot="4378945418"></ins><script>// <![CDATA[
(adsbygoogle = window.adsbygoogle || []).push({});
// ]]&gt;</script></p>
<p>Der Beitrag <a href="https://robbelroot.de/blog/ftp-string-download-in-listview/">FTP String Download in ListView</a> erschien zuerst auf <a href="https://robbelroot.de">Robert Skibbe</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://robbelroot.de/blog/ftp-string-download-in-listview/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
