How to Create a Custom View

One of the most powerful features of ListView is supporting custom views. If built-in views do not apply your scenarios, you can easily write your own. ListView will handle your views the same way with built-in views.

Creating a custom view is pretty simple. ListView control has done quiet a bit of work to make the implementation easy. Here are main steps to follow. Firstly, a class should be created and it should derive from ViewBase directly or indirectly. Then define the style of the view in a resource file. Finally link them together using ComponentResourceKey. In this blog I will show you how to create a custom view named ImageView. ImageView is used to display thumbnail of image files. The snapshot is listed below.

 Step 1. Define ImageView class

All you have to do is to subclass ViewBase.

public class ImageView : ViewBase

{

}

 Step 2. Define Style for ImageView

Two styles should be defined in a resource file. One is for ListView and the other is for ListViewItem. If you only want to do a little modification on the original one, you can use the following code. It will merge your style into its original style. The magic lies in the keyword “BasedOn”. It means your style definition is based on another style definition.

<Style TargetType="{x:Type ListView}" BasedOn="{StaticResource {x:Type ListBox}}">

NOTE: if you forget to define Template in styles, ListView will show nothing.

The following XAML code is digested from the style definitions for ImageView.

<Style TargetType="{x:Type ListView}" BasedOn="{StaticResource {x:Type ListBox}}">

  <Setter Property="BorderBrush" Value="Black"/>

  <Setter Property="BorderThickness" Value="0.5"/>

  <Setter Property="Template">

    <Setter.Value>

      <ControlTemplate>

        <Border Name="bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"

  Background="{TemplateBinding Background}" Margin="{TemplateBinding Margin}">

          <ScrollViewer Margin="{TemplateBinding Padding}">

            <WrapPanel ItemWidth="150" IsItemsHost="True" MinWidth="100"

                       Width="{Binding ActualWidth,RelativeSource={RelativeSource AncestorType=ScrollContentPresenter}}">

            </WrapPanel>

          </ScrollViewer>

        </Border>

      </ControlTemplate>

    </Setter.Value>

  </Setter>

</Style>

<Style TargetType='{x:Type ListViewItem}' BasedOn='{StaticResource {x:Type ListBoxItem}}'>

  <Setter Property='Padding' Value='3'/>

  <Setter Property='Margin' Value='5'/>

  <Setter Property='HorizontalContentAlignment' Value='Center'/>

   <Setter Property="ContentTemplate">

    <Setter.Value>

      <DataTemplate>

        <Border Background="White">

          <Image Margin="3" Source="{Binding FullName}"/>

        </Border>

      </DataTemplate>

    </Setter.Value>

  </Setter>

</Style>

Step 3. Link them together

The link method here is using ComponentResourceKey. Firstly give a key to each style defined before.

<Style x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type l:ImageView},ResourceId=ImageView}">

</Style>

<Style x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type l:ImageView},ResourceId=ImageViewItem}"}">

</Style>

Then set DefaltStyleKey and ItemContainerStyleKey in ImageView class.

public class ImageView : ViewBase

{

    protected override object DefaultStyleKey

    {

        get { return new ComponentResourceKey(GetType(), "ImageView"); }

    }

    protected override object ItemContainerDefaultStyleKey

    {

        get { return new ComponentResourceKey(GetType(), "ImageViewItem"); }

    }

}

 

Step 4. Use it in ListView

It is used like GridView.

<ListView>

  <ListView.View>

    <l:ImageView />

  </ListView.View>

</ListView>

 We’re done!

CustomView.zip