简体   繁体   中英

How can I create a 'wrapper' view which factors out common outer XAML?

In a WPF project I am creating a wizard comprising of many steps. Each step has its own view. Currently, each view has the same outer XAML elements, like a TextBlock for the title of the step, but different content below that.

So, for example a typical view would look like:

STEP X VIEW

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <TextBlock Grid.Row="0" Text="Step X text goes here"/>
    <Grid Grid.Row="1">
        <!-- CONTENT OF STEP X GOES HERE -->
    </Grid>     
</Grid>

What I would like to do is be able to 'factor out' the common outer XAML for each step into another view and just place the content of each step as the content of that new factored out view. That way, I can avoid the repetition of the same outer XAML, and if I decide to change the implementation of each step title, I only have to do it in one place.

I'm sure ContentPresenter is the part of the solution. So, something like:

WRAPPERVIEW:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <TextBlock Grid.Row="0" Text="Step X text goes here"/>
    <Grid Grid.Row="1">
        <ContentPresenter Content="Content of Step X ??????"/>
    </Grid>
</Grid>

My questions are:

1) Is my implementation of WrapperView the right way to go?

2) What is the binding for the ContentPresenter content property in WrapperView ?

3) How can I customise the Text of the TextBlock for each step using WrapperView ?

4) How can I get the client XAML using WrapperView for the XAML of any step view to look like.

So, using WrapperView for StepXView,

New STEP X VIEW

<Grid>
    <WrapperView TitleText ="Step X Title Text">
        <!-- XAML for Step X View -->
    </WrapperView>
</Grid>

You had a good intuition about using a ContentPresenter . To me, it looks exactly like you need a HeaderedContentControl , which is a templatable Control which handles both a Header and a Content property.

Although you could directly use HeaderedContentControl , I find it clearer to inherit from it in case you want to customize it further later:

public class WrapperView : HeaderedContentControl { }

And in your XAML, you can template it and use it as you wish:

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApp1">
    <Window.Resources>
        <Style TargetType="{x:Type local:WrapperView}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="local:WrapperView">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                            </Grid.RowDefinitions>
                            <ContentPresenter HorizontalAlignment="Center" Grid.Row="0" Content="{TemplateBinding Header}"/>
                            <Grid Grid.Row="1" HorizontalAlignment="Center">
                                <ContentPresenter Content="{TemplateBinding Content}"/>
                            </Grid>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <local:WrapperView Header ="Step X Title Text">
            <Rectangle Width="50" Height="50" Fill="Blue"/>
        </local:WrapperView>
    </Grid>
</Window>

The key here is the use of TemlateBinding which answers your second question.

To make it even cleaner, you could move this Style away from your Window.Resources and set it in Themes\Generics.xaml so that the Style gets applied by default.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM