Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple Content Presenters in a WPF User control

Tags:

c#

.net

wpf

xaml

I am creating a WPF user control, its like a window where most of the layout has been setup. But there are few sections where I want users to place their controls. To achieve this I believe I need to expose some dependency properties in my user control.

Output should be somewhat like this

enter image description here

Code for user control

   public class Class1 : UserControl
{
    public ContentControl Content1
    {
        get { return (ContentControl)GetValue(Content1Property); }
        set { SetValue(Content1Property, value); }
    }

    // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty Content1Property =
        DependencyProperty.Register("Content1", typeof(ContentControl), typeof(Class1), null);

    public ContentControl Content2
    {
        get { return (ContentControl)GetValue(Content2Property); }
        set { SetValue(Content2Property, value); }
    }

    // Using a DependencyProperty as the backing store for Content2.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty Content2Property =
        DependencyProperty.Register("Content2", typeof(ContentControl), typeof(Class1), null);


    public ContentControl Content3
    {
        get { return (ContentControl)GetValue(Content3Property); }
        set { SetValue(Content3Property, value); }
    }

    // Using a DependencyProperty as the backing store for Content3.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty Content3Property =
        DependencyProperty.Register("Content3", typeof(ContentControl), typeof(Class1),null);


}

And the respective xaml of the control is

 <Style TargetType="{x:Type userControl:Class1}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="userControl:Class1">
                <Grid ShowGridLines="True">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="10"></ColumnDefinition>
                        <ColumnDefinition Width="Auto"></ColumnDefinition>
                        <ColumnDefinition Width="10"></ColumnDefinition>
                        <ColumnDefinition Width="Auto"></ColumnDefinition>
                        <ColumnDefinition Width="10"></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="10"></RowDefinition>
                        <RowDefinition Height="Auto"></RowDefinition>
                        <RowDefinition Height="10"></RowDefinition>
                        <RowDefinition Height="Auto"></RowDefinition>
                        <RowDefinition Height="10"></RowDefinition>
                        <RowDefinition Height="Auto"></RowDefinition>
                        <RowDefinition Height="10"></RowDefinition>
                    </Grid.RowDefinitions>
                    <TextBlock Grid.Row="1" Grid.Column="1" Text="First Content"></TextBlock>
                    <ContentPresenter x:Name="firstContentPresenter" ContentSource="{TemplateBinding Content1}" Grid.Row="1" Grid.Column="3"></ContentPresenter>


                    <TextBlock Grid.Row="3" Grid.Column="1" Text="First Content"></TextBlock>
                    <ContentPresenter x:Name="secondContentPresenter"  ContentSource="{TemplateBinding Content2}"  Grid.Row="3" Grid.Column="3"></ContentPresenter>

                    <TextBlock Grid.Row="5" Grid.Column="1" Text="First Content"></TextBlock>
                    <ContentPresenter x:Name="thirdContentPresenter"  ContentSource="{TemplateBinding Content3}"  Grid.Row="5" Grid.Column="3"></ContentPresenter>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

And I am trying to use it somewhat like this

 <userControl:Class1 Width="200" Height="200" Background="GreenYellow">

    <userControl:Class1.Content1>
        <Label>I am number 1</Label>
    </userControl:Class1.Content1>
    <userControl:Class1.Content2>
        <Label>I am number 2</Label>
    </userControl:Class1.Content2>
    <userControl:Class1.Content3>
        <Label>I am number 3</Label>
    </userControl:Class1.Content3>
</userControl:Class1>

The output of the above code is nothing.

enter image description here

like image 304
Manvinder Avatar asked Aug 09 '13 06:08

Manvinder


People also ask

What is the difference between user control and custom control in wpf?

A customControl can be styled and templated and best suited for a situation when you are building a Control Library. On the contrary, a UserControl gives you an easy way to define reusable chunk of XAML which can be reused widely in your application and when you don't need to use it as a Control Library .

How can I access a control in wpf from another class or window?

If you want to access a control on a wpf form from another assembly you have to use the modifier attribute x:FieldModifier="public" or use the method proposed by Jean. Save this answer.

What is UserControl wpf?

User controls, in WPF represented by the UserControl class, is the concept of grouping markup and code into a reusable container, so that the same interface, with the same functionality, can be used in several different places and even across several applications.


1 Answers

Class1.cs changes:

public class Class1 : Control {
  public Class1() {
    this.DefaultStyleKey = typeof(Class1);
  }

  public object Content1 {
    get { return GetValue(Content1Property); }
    set { SetValue(Content1Property, value); }
  }

  // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
  public static readonly DependencyProperty Content1Property =
      DependencyProperty.Register("Content1", typeof(object), typeof(Class1), null);

  public object Content2 {
    get { return GetValue(Content2Property); }
    set { SetValue(Content2Property, value); }
  }

  // Using a DependencyProperty as the backing store for Content2.  This enables animation, styling, binding, etc...
  public static readonly DependencyProperty Content2Property =
      DependencyProperty.Register("Content2", typeof(object), typeof(Class1), null);


  public object Content3 {
    get { return GetValue(Content3Property); }
    set { SetValue(Content3Property, value); }
  }

  // Using a DependencyProperty as the backing store for Content3.  This enables animation, styling, binding, etc...
  public static readonly DependencyProperty Content3Property =
      DependencyProperty.Register("Content3", typeof(object), typeof(Class1), null);
}

Style changes (Dictionary1.xaml):

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:ui="clr-namespace:WpfApplication1"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Style TargetType="ui:Class1">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ui:Class1">
                        <Grid ShowGridLines="True">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="10"></ColumnDefinition>
                                <ColumnDefinition Width="Auto"></ColumnDefinition>
                                <ColumnDefinition Width="10"></ColumnDefinition>
                                <ColumnDefinition Width="Auto"></ColumnDefinition>
                                <ColumnDefinition Width="10"></ColumnDefinition>
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="10"></RowDefinition>
                                <RowDefinition Height="Auto"></RowDefinition>
                                <RowDefinition Height="10"></RowDefinition>
                                <RowDefinition Height="Auto"></RowDefinition>
                                <RowDefinition Height="10"></RowDefinition>
                                <RowDefinition Height="Auto"></RowDefinition>
                                <RowDefinition Height="10"></RowDefinition>
                            </Grid.RowDefinitions>
                            <TextBlock Grid.Row="1" Grid.Column="1" Text="First Content"></TextBlock>
                            <ContentPresenter x:Name="firstContentPresenter" Content="{TemplateBinding Content1}" Grid.Row="1" Grid.Column="3"></ContentPresenter>


                            <TextBlock Grid.Row="3" Grid.Column="1" Text="First Content"></TextBlock>
                            <ContentPresenter x:Name="secondContentPresenter"  Content="{TemplateBinding Content2}"  Grid.Row="3" Grid.Column="3"></ContentPresenter>

                            <TextBlock Grid.Row="5" Grid.Column="1" Text="First Content"></TextBlock>
                            <ContentPresenter x:Name="thirdContentPresenter"  Content="{TemplateBinding Content3}"  Grid.Row="5" Grid.Column="3"></ContentPresenter>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ResourceDictionary>

MainWindow.xaml:

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:ui="clr-namespace:WpfApplication1"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <ui:Class1 Width="200" Height="200">
                <ui:Class1.Content1>
                    <Label x:Name="lbl">rrrr</Label>
                </ui:Class1.Content1>
                <ui:Class1.Content2>
                    <Label>eee</Label>
                </ui:Class1.Content2>
                <ui:Class1.Content3>
                    <Label>ffff</Label>
                </ui:Class1.Content3>
            </ui:Class1>
        </Grid>
  </Window>

Attaching dictionary (App.xaml):

<Application x:Class="WpfApplication1.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Dictionary1.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>

    </Application.Resources>
</Application>

enter image description here

This works for me.

like image 76
Ondrej Svejdar Avatar answered Sep 29 '22 09:09

Ondrej Svejdar