I recentrly discovered "reusable controls" in WPF and I have a project where they seem to provide me with a solution to a problem I have.
Let me sketch the situation: I need to make several UI elements. All of them share a common base, a common style/layout/template let's say, and they also share some common logic.
Next to that, all of these elements have some element-specific stuff.
You could say that I have some kind of inheritance here, but then for both XAML and CS.
The way I wanted to solve this, was by making an outer reusable element, I made a small example. The common part Is the Title
label and the border. The element-specific UI can then be inserted into UserContent
.
The code looks something like this (although it's simplified for the sake of brevity and conciseness, I also have an eventhandler and a routed event in my actual application):
ReusableControl.xaml
<UserControl x:Class="StackOverflowQuestion4.ReusableControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="root">
<Border BorderBrush="Black"
BorderThickness="1"
Width="400"
Height="200">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Content="{Binding Title, ElementName=root}"
Grid.Row="0"/>
<ContentControl Content="{Binding UserContent, ElementName=root}"
Grid.Row="1"/>
</Grid>
</Border>
</UserControl>
ReusableControl.xaml.cs
using System.Windows;
using System.Windows.Controls;
namespace StackOverflowQuestion4
{
public partial class ReusableControl : UserControl
{
public ReusableControl()
{
InitializeComponent();
}
public string Title
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(string), typeof(ReusableControl), new PropertyMetadata(string.Empty));
public object UserContent
{
get { return GetValue(UserContentProperty); }
set { SetValue(UserContentProperty, value); }
}
public static readonly DependencyProperty UserContentProperty =
DependencyProperty.Register("UserContent", typeof(object), typeof(ReusableControl), new PropertyMetadata(string.Empty));
}
}
Lovely, I can now use my special control in other parts of my code, and I can insert whatever I want into the UserContent
field.
MainWindow.xaml
<Window x:Class="StackOverflowQuestion4.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:StackOverflowQuestion4"
mc:Ignorable="d"
Title="MainWindow"
SizeToContent="WidthAndHeight">
<Grid Width="800"
Height="600">
<local:ReusableControl Title="Test">
<local:ReusableControl.UserContent>
<Rectangle Width="300"
Height="100"
Fill="Blue"/>
</local:ReusableControl.UserContent>
</local:ReusableControl>
</Grid>
</Window>
This works great, but the problem arises when I start to name things. Simply adding a name to an element inside of my ReusableControl
causes a compilation error.
<Rectangle Width="300"
Height="100"
Fill="Blue"
Name="LolWhatAmIDoing"/>
I get the following error:
MC3093 - Cannot set Name attribute value 'LolWhatAmIDoing' on element 'Rectangle'. 'Rectangle' is under the scope of element 'ReusableControl', which already had a name registered when it was defined in another scope.
This seems like such a small issue, but I cannot find an easy solution to this problem.
I found this thread on the forum, but it does not really provide a solution. Since I'm pretty new to all of this, I also don't really get what the issue is, so apologies if I'm slow minded.
Should I move to CustomControls?