Blog Archives

WPF ListView – Formatting Rows

 By the end of the previous blog item on the topic of the WPF ListView, the ListView looked like this:

In this blog I want to look at ways of changing the look of the rows. You may, for example, want to assign a background color to the rows. And based on what we have done so far, you might be tempted to edit the DataTemplates used for the cells. Maybe you would think about adding a Border with a Background fill and placing this around the TextBlock for each cell:  

  <DataTemplate x:Key="IDCellTemplate2">

      <Border Background="LightGreen">

      <TextBlock Foreground="MediumBlue"

                FontFamily="Calibri"

         Text="{Binding Path=ProductID}" />

      </Border>

    </DataTemplate> 

I won't waste the space showing the markup for all three templates here, but if you did try this you will get a disappointing result:

Pretty ugly, I think you'll agree. Playing around with the Margin or Padding won't get you any further either.

The answer is to use the ItemContainerStyle property of the ListView. This opens up a number of choices for you. Firstly, if you would like to still have a gap between each of the columns – but an even gap – then you can take the following approach:  

      <ListView.ItemContainerStyle>

        <Style TargetType="ListViewItem">

          <Setter Property="HorizontalContentAlignment" Value="Stretch" />

        </Style>

      </ListView.ItemContainerStyle> 

This will produce the following output, which is an improvement:

If you want the light green to spread across the whole row, then you still use the ItemContainerStyle, but this time you set the Background property of the ListViewItem:  

      <ListView.ItemContainerStyle>

        <Style TargetType="ListViewItem">

            <Setter Property="Background" Value="LightGreen" />

        </Style>

      </ListView.ItemContainerStyle> 

Now you get the result you are probably looking for.

 

If all that whiteness in the background is a bit too much for you, then of course you can blend another shade of green into the mix by setting the ListView's Background property. Using SeaGreen, for example, will produce this:

 

 

The final markup for the ListView looks like this:  

    <ListView Name="ProductsListView"

         ItemsSource="{Binding}"

           Margin="5,25"

              Background="SeaGreen">

      <ListView.ItemContainerStyle>

        <Style TargetType="ListViewItem">

            <Setter Property="Background" Value="LightGreen" />

        </Style>

      </ListView.ItemContainerStyle>

 

      <ListView.View>

        <GridView>

          <!– Product ID –>

          <GridViewColumn

           HeaderTemplate="{StaticResource IDColHeader}"

          CellTemplate="{StaticResource IDCellTemplate}">

          </GridViewColumn>

          <!– Product Name –>

          <GridViewColumn

           HeaderTemplate="{StaticResource NameColHeader}"

           CellTemplate="{StaticResource NameCellTemplate}">

          </GridViewColumn>

          <!– Pack Size –>

          <GridViewColumn

           HeaderTemplate="{StaticResource PackageColHeader}"

           CellTemplate="{StaticResource PackCellTemplate}">

          </GridViewColumn>

        </GridView>

      </ListView.View>

    </ListView> 

The markup for the DataTemplates and Styles is the same as that shown in the previous blog, all of which I placed in the Application.xaml file (App.xaml for C# projects).

There are some other row formatting options I want to cover, but I will leave those for another day.

WPF ListView: DataBinding and Column Headers

 A recent question on VBCity came from a developer who was searching for a way of changing the background color, font and border of the Column Headers in a ListView. This has always been a particularly tough call in Windows Forms. (A DataGridView, on the other hand, does have this feature, so that might often be an easy workaround.)

But, as usual when questions of difficult layout come up, my mind turns to WPF as a possible solution. Usually I would say 'an easy solution', but in this case honesty forces me to say that I've always found the WPF ListView to be one of its less user-friendly elements. Windows Forms certainly makes it easier to create data by hand, with the ability to add sub-items via the properties window. WPF effectively forces you to use data binding as the means of populating the ListView – although the data source can be a relatively simple collection of objects.   So I thought it might be useful to blog how to create a relatively uncomplicated ListView in WPF – one with a differently colored Column Headers,of course.

There is quite a lot of repetition of the graphical characteristics of the various sub-elements of a WPF ListView – the Column Headers and the content of the columns themselves, for example. So, it is always worth spending the time to create Styles or Templates which can be reused. Not only does this save time in the long run, it reduces the amount of markup used to create the actual ListView itself in the Window which usually makes it a little easier to read.

The first version isn't going to be too ambitious and will look like this:

  

Of course I could have added lots of other graphics junk in there, but I want to try and keep things as straightforward as possible. By the time we've worked our way through the Styles, Templates and XML Data Provider, I think that will be quite enough for one session. In a later blog, I plan to expand on this version.

The Basic ListView
The first step is to drag an empty ListView from the Toolbox and drop it on the XAML pane. Note that I say XAML pane, not the Design pane. As in this case, it is often easier to start with an empty element rather than have to edit the default property settings that you will see in the XAML if you drop it on to the Design pane.

In order to display the content, a WPF ListView requires the use of a View. This has the same role as the View property in the Windows Forms ListView, i.e. it controls the manner in which the data is laid out. The similarities end there, however. At the time of writing, the WPF ListView only has one choice of view – the GridView. In its basic form, this is similar to the WinForms ListView Details View, (except of course that WPF isn't limited in the way you can package and display the data).

As you can see from the following screenshot, even if you wanted to choose a value for the View property, this is something that has to be created in XAML. Future versions of WPF may perhaps increase this choice, but WPF already gives you the freedom to use the equivalent of Large Icon, Small Icon, List, etc, if that is the look you want, so maybe not.

  

The markup to create the View is simple: 

      <ListView >

         <ListView.View>

             <GridView>

 

             </GridView>

         </ListView.View>

       </ListView>

 There will be very little to see in the Design Pane yet. The next step is to add some columns. Add three columns to the GridView of the ListView:

                <GridView>

            <GridViewColumn Width="85">

            </GridViewColumn>

            <GridViewColumn></GridViewColumn>

            <GridViewColumn></GridViewColumn>

        </GridView>

 If you check the Design pane now, you will see a fine outline of the Column Headers. There is a divider after the first column, because I have set a Width value on it. The other two columns are not visible because they currently have a zero width.

  

Create a Reusable Style
Each of the three Column Headers will have some properties that are set to the same values as each other. Therefore it makes sense to set those property values in one place and assign them to each Column Header. The alternative approach would be to repeat virtually the same XAML three times, which clearly isn't a sensible way forward. WPF Styles is the technique which makes this very easy to implement.

In this simple example I am going to use a TextBlock to hold the text of the Column Header. The following markup, which is placed in the Application.xaml file (for VB) or App.xaml file (for C#) creates a Style for a TextBlock:  

    <Style x:Key="ColHeaderText" TargetType="TextBlock">

      <Setter Property="Width" Value="110" />

      <Setter Property="Height" Value="29" />

      <Setter Property="FontSize" Value="14" />

      <Setter Property="FontWeight" Value="Bold" />

      <Setter Property="Background" Value="Yellow" />

      <Setter Property="Foreground" Value="Navy" />

    </Style>

 If you're not familiar with the concept of Styles, all it does is set values on an assortment of TextBlock properties. The Style is assigned a key – in this case 'ColHeaderText'. This Style can now be applied to any TextBlock in the application.

The markup for the ListView can now be extended to include a Header that contains a TextBlock:  

 <GridViewColumn Width="85">

             <GridViewColumn.Header>

              <TextBlock Text=" Product ID"

              Style="{StaticResource ColHeaderText}"  />

            </GridViewColumn.Header>

          </GridViewColumn>

 The TextBlock created by this markup has Text content of 'Product ID' and its color, font, etc are all set by the values stored in the Style. You can see the result in the Design pane screenshot below.

 

  

In the final version, I have added similar markup for the remaining two columns. I have left them out of the snippet above for brevity.

Populating with Data
As I mentioned earlier, you need to use some form of data binding to populate the ListView. In this example I am using a simple XML file. You can view this file here. The markup that creates the link between the application and the XML file is straightforward:

 

    <XmlDataProvider x:Key="ProductList" Source="Products.xml" />

 

It uses an XMLDataProvider which I've keyed as 'ProductList' so that it can be referred to elsewhere in the project. The source data comes from the Products.xml file, which is located with the other project files in Solution Explorer.

Now that we have a data source, the ListView's ItemsSource property can be set to point to it. The markup is a bit tortuous, but not as complex as it might first appear. Essentially, the ItemsSource property is assigned a Binding and that Binding links to the ProductsList data provider. From the ProductsList, XPath syntax is used to point directly to the Product elements in the XML file. XPath isn't always the easiest syntax to use, but in the case of our simple XML file this is relatively straightforward.  

ItemsSource="{Binding Source={StaticResource ProductList}, XPath=Products/Product}" 

Next, the various columns can be bound to the appropriate fields. The GridViewColumn has a DisplayMemberBinding property which , as its name implies, sets the Binding to be used for the content of the column. Once again, XPath is used for this.  

   DisplayMemberBinding="{Binding XPath=ProductID}" 

In the above snippet, DisplayMemberPath is assigned a Binding which links back to the ProductID element of the Products.xml file. (Note: If the field in the data source is an XML Attribute, as opposed to an Element, it is necessary to add a leading @ symbol to the XPath name.)

For this basic ListView, that's all that is needed. You can view the Application.xaml file here, and the markup for the Window here. In a future blog, I'll improve this basic version and look at some other functionality, but if you haven't previously dealt with WPF ListViews I hope this will get you started.

WP Like Button Plugin by Free WordPress Templates