Mark Ingram
Mark Ingram

Reputation: 73713

WPF How to write a reuseable derived control with templating

I want to create a reuseable control, based on a ListView. This derived ListView is exactly the same as the original, except it has a button on each row (outside of the ContentPresenter).

If I use XAML to define my control, I can't then add this control to a window's XAML, and add things like resources, etc, as they have already been defined.

What is the correct way of doing this?

I have the following style that I want to apply:

<Style x:Key="MyListViewStyle" TargetType="{x:Type MyListViewItem}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type MyListViewItem}">
                <Grid>
                    ...
                    <ToggleButton .../>
                    <Border ...>
                        <ContentPresenter .../>
                    </Border>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

But how can I apply this, and be able to use the control in my Window's XAML? I need to be able to change the default template like this, as I want the end user of the control to be able to add whatever controls they like to each row via the ContentPresenter.

How does Microsoft apply the default styles for each of their controls?

I'm trying to write an encapsulated control, one which the end user doesn't need to know about the content template (the control is in a separate assembly to the application). This is how I want to use my control:

<MyListView DataContext="{StaticResource MyDataSource}" ItemsSource="{Binding Items}">
    <MyListView .ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <Image Width="32" Height="32" Source="{Binding Image}" />
                <TextBlock Text="{Binding Text}" />
            </StackPanel>
        </DataTemplate>
    </MyListView.ItemTemplate>


    <MyListView.Resources>
        <Style TargetType="{x:Type MyListViewItem}">
            <Setter Property="IsChecked" Value="{Binding IsChecked, Mode=TwoWay}" />
        </Style>
    </MyListView.Resources>

</MyListView>

Upvotes: 1

Views: 196

Answers (1)

pushpraj
pushpraj

Reputation: 13679

Let's start deploying a custom control with default templates

  • Create a class library project

  • Add your necessary custom controls in the project as needed

  • Add a resource dictionary to the project

  • name the file generic.xaml and place in themes folder

read here why the name generic.xaml is important http://social.msdn.microsoft.com/Forums/vstudio/en-US/641a1f97-271f-4f86-a670-8b3a0a8d8d9f/what-is-so-special-about-genericxaml

  • create your default styles in resource dictionaries without keys, styles will target your custom types

eg.

<ResourceDictionary>
    <Style TargetType="{x:Type MyListViewItem}">
        <Setter Property="Template">
           <Setter.Value>
                <ControlTemplate TargetType="{x:Type MyListViewItem}">
                    <Grid>
                        ...

then you need to specify the default dictionary location via ThemeInfo attribute in assemblyinfo.cs of class library project

[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]

so this attribute will determine where to look for the style resources

Compile the project and reference the output library in the target application and place the desired custom control to the window or other user control and see the default style being picked up from the source assembly

eg.

<MyListView DataContext="{StaticResource MyDataSource}" ItemsSource="{Binding Items}"/>

more info on ThemeInfo attribute http://msdn.microsoft.com/en-us/library/system.windows.themeinfoattribute(v=vs.110).aspx

Upvotes: 1

Related Questions