Reputation: 4782
I try to create a "container" user control that can display UIElement
objects as child in WPF. The usage of the control should look like this:
<general:DisplayContainer Title="Hello">
<TextBlock x:Name="AnyUIElement" />
</general:DisplayContainer>
where the TextBlock is just an example. So far I created the UserControl and bind the Title property like this:
<Grid x:Name="Grid_Main">
<Border x:Name="Border_Main" BorderThickness="2" Margin="10" CornerRadius="5" Padding="7" />
<TextBlock x:Name="TextBlock_Title" Background="{Binding Background, ElementName=Grid_Main}" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Path=Title, FallbackValue=Title}" Margin="20,2,0,0" Padding="3,0" />
</Grid>
The Codebehind file looks like this:
public partial class DisplayContainer : UserControl
{
public DisplayContainer()
{
InitializeComponent();
this.DataContext = this;
}
public string Title
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title",typeof(string), typeof(DisplayContainer));
}
Now, how can I modify my control in a way, that i accepts a child element in the XAML-file, when I use the control? The child should be displayed through the Border_Main.Child
Property.
Thanks in advance,
Frank
Upvotes: 2
Views: 3472
Reputation: 4322
Or, yet another way.
You can add many DPs if you needed to have different sections. Just add more ContentPresenters bound to the different DPs (Child, Header, Footer, etc..).
DisplayContainer.cs
[System.Windows.Markup.ContentProperty("Child")]
public partial class DisplayContainer : UserControl
{
public DisplayContainer()
{
InitializeComponent();
}
public string Title
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(DisplayContainer));
public UIElement Child
{
get { return (UIElement)GetValue(ChildProperty); }
set { SetValue(ChildProperty, value); }
}
public static readonly DependencyProperty ChildProperty = DependencyProperty.Register("Child", typeof(UIElement), typeof(DisplayContainer));
}
DisplayContainer.xaml
<UserControl x:Class="WpfApp19.DisplayContainer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp19"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid x:Name="Grid_Main">
<Border x:Name="Border_Main" BorderThickness="2" Margin="10" CornerRadius="5" Padding="7">
<ContentPresenter Content="{Binding Child, RelativeSource={RelativeSource AncestorType=UserControl}}" />
</Border>
<TextBlock x:Name="TextBlock_Title" Background="{Binding Background, ElementName=Grid_Main}" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Path=Title, FallbackValue=Title, RelativeSource={RelativeSource AncestorType=UserControl}}" Margin="20,2,0,0" Padding="3,0" />
</Grid>
</UserControl>
MainWindow.xaml
<Window x:Class="WpfApp19.MainWindow"
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"
xmlns:general="clr-namespace:WpfApp19"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<general:DisplayContainer Title="Hello">
<StackPanel>
<TextBlock Text="Test1" />
<TextBlock Text="Test2" />
</StackPanel>
<!-- Alternative way of setting Child - if you had more DPs (Header, Footer, etc..) you would have to set their content this way
<general:DisplayContainer.Child>
<TextBlock Text="AnyUIElement" />
</general:DisplayContainer.Child>
-->
</general:DisplayContainer>
</Grid>
</Window>
Upvotes: 1
Reputation: 169190
Or you could define a DisplayContainer
as a ContentControl
without a .xaml
file but with a ControlTemplate
:
public partial class DisplayContainer : ContentControl
{
public DisplayContainer()
{
this.DataContext = this;
}
public string Title
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(string), typeof(DisplayContainer));
}
XAML:
<Window x:Class="WpfApp1.MainWindow"
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"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="300" Width="300">
<Window.Resources>
<Style TargetType="local:DisplayContainer">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:DisplayContainer">
<Grid x:Name="Grid_Main">
<Border x:Name="Border_Main" BorderThickness="2" Margin="10" CornerRadius="5" Padding="7">
<ContentPresenter />
</Border>
<TextBlock x:Name="TextBlock_Title" Background="{Binding Background, ElementName=Grid_Main}"
HorizontalAlignment="Left" VerticalAlignment="Top"
Text="{Binding Path=Title, RelativeSource={RelativeSource AncestorType=local:DisplayContainer}, FallbackValue=Title}" Margin="20,2,0,0" Padding="3,0" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel>
<local:DisplayContainer Title="Hello">
<TextBlock Text="AnyUIElement..." />
</local:DisplayContainer>
</StackPanel>
</Window>
Upvotes: 1
Reputation: 128061
Just set the UserControl's Template property
<UserControl ...>
<UserControl.Template>
<ControlTemplate TargetType="UserControl">
<StackPanel>
<TextBlock Text="{Binding Title,
RelativeSource={RelativeSource AncestorType=UserControl}}"/>
<ContentPresenter />
</StackPanel>
</ControlTemplate>
</UserControl.Template>
</UserControl>
and put the displayed element in the UserControl's Content:
<local:DisplayContainer Title="A Title">
<TextBlock Text="Hello"/>
</local:DisplayContainer>
Upvotes: 4