Question

I want to write a ContentControl to host other controls and give them a special border.

So I added a new UserControl, made a ContentControl of it. It is having a grid, on the outer sides I want to have the border.

So the first question is: Is this a good approach to achieve a "Bordered" Control?

Here is the XAML

<ContentControl x:Class="DemoApplication.Controls.ImpressedContentControl"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                Name="ImpressedContent"
                d:DesignHeight="300"
                d:DesignWidth="300"
                mc:Ignorable="d">
    <Grid>
        <Grid.Resources>
            <ImageBrush x:Key="ImpressedLeftBrush"
                        ImageSource="/DemoApplication;component/Images/Impressed_left.png"
                        TileMode="FlipY"
                        Viewport="0,0,100,100"
                        ViewportUnits="Absolute" />
            <ImageBrush x:Key="ImpressedRightBrush"
                        ImageSource="/DemoApplication;component/Images/Impressed_right.png"
                        TileMode="FlipY"
                        Viewport="0,0,100,100"
                        ViewportUnits="Absolute" />
            <ImageBrush x:Key="ImpressedTopBrush"
                        ImageSource="/DemoApplication;component/Images/Impressed_top.png"
                        TileMode="FlipY"
                        Viewport="0,0,100,100"
                        ViewportUnits="Absolute" />
            <ImageBrush x:Key="ImpressedBottomBrush"
                        ImageSource="/DemoApplication;component/Images/Impressed_bottom.png"
                        TileMode="FlipY"
                        Viewport="0,0,100,100"
                        ViewportUnits="Absolute" />
        </Grid.Resources>
        <Grid.RowDefinitions>
            <RowDefinition Height="4" />
            <RowDefinition Height="1*" />
            <RowDefinition Height="4" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="4" />
            <ColumnDefinition Width="1*" />
            <ColumnDefinition Width="4" />
        </Grid.ColumnDefinitions>

        <Grid Grid.Row="0"
              Grid.Column="1"
              Background="{DynamicResource ImpressedTopBrush}" />
        <Grid Grid.Row="2"
              Grid.Column="1"
              Background="{DynamicResource ImpressedBottomBrush}" />
        <Grid Grid.Row="1"
              Grid.Column="0"
              Background="{DynamicResource ImpressedLeftBrush}" />
        <Grid Grid.Row="1"
              Grid.Column="2"
              Background="{DynamicResource ImpressedRightBrush}" />

        <ContentControl Grid.Row="1"
                   Grid.Column="1"
                   HorizontalAlignment="Stretch"
                   VerticalAlignment="Stretch"
                   Content="{Binding ElementName=ImpressedContent,
                                  Path=ControlContent}" />

    </Grid>
</ContentControl>

In the codebehind I have a DependencyProperty to set the content.

    public partial class ImpressedContentControl : ContentControl
    {
        public ImpressedContentControl()
        {
            InitializeComponent();
        }

        public Control ControlContent
        {
            get { return (Control)GetValue(ControlContentProperty); }
            set { SetValue(ControlContentProperty, value); }
        }

        public static readonly DependencyProperty ControlContentProperty =
          DependencyProperty.Register("ControlContent", typeof(Control), typeof(ImpressedContentControl), new UIPropertyMetadata(""));
    }

I want to use it somewhat like

<controls:ImpressedContentControl Grid.Column="1">
            <ControlContent>
                <TextBlock Text="FooBar Text" />
            </ControlContent>
</controls:ImpressedContentControl>

Is it possible to use the Content property of the ContentControl somehow?

Is there an easier way to achieve that?

Any ideas highly appeciated!

Was it helpful?

Solution

I believe you should use WPF control template here. It's very easy to give any control a template that defines its visual appearance. In your case you can define the template for your ImpressedContentControl like this

<ContentControl x:Class="DemoApplication.Controls.ImpressedContentControl"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                Name="ImpressedContent"
                d:DesignHeight="300"
                d:DesignWidth="300"
                mc:Ignorable="d">
       <!--define control template-->
      <ContentControl.Template>
        <ControlTemplate TargetType="{x:Type ContentControl}">
            <Grid>
                <Grid.Resources>
                    <ImageBrush x:Key="ImpressedLeftBrush"
                        ImageSource="/DemoApplication;component/Images/Impressed_left.png"
                        TileMode="FlipY"
                        Viewport="0,0,100,100"
                        ViewportUnits="Absolute" />
                    <ImageBrush x:Key="ImpressedRightBrush"
                        ImageSource="/DemoApplication;component/Images/Impressed_right.png"
                        TileMode="FlipY"
                        Viewport="0,0,100,100"
                        ViewportUnits="Absolute" />
                    <ImageBrush x:Key="ImpressedTopBrush"
                        ImageSource="/DemoApplication;component/Images/Impressed_top.png"
                        TileMode="FlipY"
                        Viewport="0,0,100,100"
                        ViewportUnits="Absolute" />
                    <ImageBrush x:Key="ImpressedBottomBrush"
                        ImageSource="/DemoApplication;component/Images/Impressed_bottom.png"
                        TileMode="FlipY"
                        Viewport="0,0,100,100"
                        ViewportUnits="Absolute" />
                </Grid.Resources>
                <Grid.RowDefinitions>
                    <RowDefinition Height="4" />
                    <RowDefinition Height="1*" />
                    <RowDefinition Height="4" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="4" />
                    <ColumnDefinition Width="1*" />
                    <ColumnDefinition Width="4" />
                </Grid.ColumnDefinitions>

                <Grid Grid.Row="0"
              Grid.Column="1"
              Background="{DynamicResource ImpressedTopBrush}" />
                <Grid Grid.Row="2"
              Grid.Column="1"
              Background="{DynamicResource ImpressedBottomBrush}" />
                <Grid Grid.Row="1"
              Grid.Column="0"
              Background="{DynamicResource ImpressedLeftBrush}" />
                <Grid Grid.Row="1"
              Grid.Column="2"
              Background="{DynamicResource ImpressedRightBrush}" />

                <!--Use ContentPresenter to display inner content-->
                <ContentPresenter Grid.Row="1" Grid.Column="1"></ContentPresenter>

            </Grid>
        </ControlTemplate>
      </ContentControl.Template>   
    </ContentControl>

And use your control like this

<controls:ImpressedContentControl Grid.Column="1">
            <TextBlock Text="FooBar Text" />
</controls:ImpressedContentControl>

There is no need for the ImpressedContent Dependency property. In fact you could do all of this without even creating new control class, just by using only base ContentControl and applying new style to it that uses the below template.

You can find here more about WPF control templates

http://msdn.microsoft.com/en-us/library/ee230084.aspx

http://msdn.microsoft.com/en-us/magazine/cc163497.aspx

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top