In order to be able to expose custom properties that take advantage of xaml data binding, you need to use dependency properties.
In this simple example we create a user control exposing four dependency properties, which will allow our developers to be able to create the following instance:
Our User Control
For each property you’ll need a dependency property field which gets exposed through a normal .NET property wrapper. This is to enable Xaml to make use of the data binding system:
PlayerControl.xaml.cs
using System.ComponentModel;
using System.Windows;
using System.Windows.Media;
namespace WpfCustomUserControl
{
public partial class PlayerControl
{
#region Dependency Properties
public static readonly DependencyProperty ShirtNumberProperty =
DependencyProperty.Register("ShirtNumber",
typeof(int),
typeof(PlayerControl),
new PropertyMetadata(0));
[Bindable(true)]
public int ShirtNumber
{
get { return (int)this.GetValue(ShirtNumberProperty); }
set { this.SetValue(ShirtNumberProperty, value); }
}
public static readonly DependencyProperty KitColorProperty =
DependencyProperty.Register("KitColor",
typeof(Brush),
typeof(PlayerControl),
new PropertyMetadata(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0))));
[Bindable(true)]
public Brush KitColor
{
get { return (Brush)this.GetValue(KitColorProperty); }
set { this.SetValue(KitColorProperty, value); }
}
public static readonly DependencyProperty SurnameProperty =
DependencyProperty.Register("Surname",
typeof(string),
typeof(PlayerControl),
new PropertyMetadata("Not set"));
[Bindable(true)]
public string Surname
{
get { return (string)this.GetValue(SurnameProperty); }
set { this.SetValue(SurnameProperty, value); }
}
public static readonly DependencyProperty PositionProperty =
DependencyProperty.Register("Position",
typeof(string),
typeof(PlayerControl),
new PropertyMetadata("Not set"));
[Bindable(true)]
public string Position
{
get { return (string)this.GetValue(PositionProperty); }
set { this.SetValue(PositionProperty, value); }
}
#endregion
public PlayerControl()
{
InitializeComponent();
}
}
}
Note: I've included a bindable attribute to the dependency properties that is not required but I add as a best practice.
The xaml for our user control can then hook up the data binding.
PlayerControl.xaml
<UserControl x:Class="WpfCustomUserControl.PlayerControl"
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"
x:Name="CustomPlayer"
Width="120"
Height="90"
mc:Ignorable="d">
<Grid>
<Button>
<StackPanel>
<Ellipse Width="30"
Height="30"
Fill="{Binding Path=KitColor,
ElementName=CustomPlayer,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Margin="0,-25"
HorizontalAlignment="Center"
FontSize="16"
Foreground="White"
Text="{Binding Path=ShirtNumber,
ElementName=CustomPlayer,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Margin="0,10,0,5"
HorizontalAlignment="Center"
FontSize="15"
Text="{Binding Path=Surname,
ElementName=CustomPlayer,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
<TextBlock HorizontalAlignment="Center"
Text="{Binding Path=Position,
ElementName=CustomPlayer,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
</Button>
</Grid>
</UserControl>
Note: No data binding is set on the user control as this will be set at runtime by the developer using the usercontrol. The element name within the usercontrols controls points to itself to enable data binding to work.
We can now easily reuse our user control setting the properties for each instance.
MainWindow.xaml
<Window x:Class="WpfCustomUserControl.MainWindow"Source code: http://stevenhollidge.com/blog-source-code/WpfCustomUserControl.zip
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfCustomUserControl"
Title="England Footy Team"
Icon="Football.ico"
Height="500" Width="600">
<Grid x:Name="mainGrid">
<Grid.RowDefinitions>
<RowDefinition Height="10"/>
<RowDefinition Height="100"/>
<RowDefinition Height="120"/>
<RowDefinition Height="120"/>
<RowDefinition Height="120"/>
<RowDefinition Height="10"/>
</Grid.RowDefinitions>
<Grid.Resources>
<Style TargetType="WrapPanel">
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
</Grid.Resources>
<WrapPanel Name="panelGoalKeeper" Grid.Column="0" Grid.Row="1">
<local:PlayerControl x:Name="btnGK"
ShirtNumber="1"
KitColor="Green"
Surname="Hart"
Position="Keeper" />
</WrapPanel>
<WrapPanel Name="panelDefenders" Grid.Column="0" Grid.Row="2">
<local:PlayerControl x:Name="btnDF1"
ShirtNumber="2"
KitColor="Crimson"
Surname="Richards"
Position="Strong as an Ox"
Margin="0,25,25,0"/>
<local:PlayerControl x:Name="btnDF2"
ShirtNumber="5"
KitColor="Crimson"
Surname="Cahill"
Position="Ball playing stopper"
Margin="0,0,5,0"/>
<local:PlayerControl x:Name="btnDF3"
ShirtNumber="6"
KitColor="Crimson"
Surname="Jones"
Position="Marauding Sweeper"
Margin="5,0,0,0"/>
<local:PlayerControl x:Name="btnDF4"
ShirtNumber="3"
KitColor="Crimson"
Surname="Baines"
Position="Freekick specialist"
Margin="25,25,0,0"/>
</WrapPanel>
<WrapPanel Name="panelMidfielders" Grid.Column="0" Grid.Row="3">
<local:PlayerControl x:Name="btnMD1"
ShirtNumber="7"
KitColor="Crimson"
Surname="Wilshire"
Position="Playmaker"
Margin="0,25,25,0"/>
<local:PlayerControl x:Name="btnMD2"
ShirtNumber="4"
KitColor="Crimson"
Surname="Parker"
Position="Battler" />
<local:PlayerControl x:Name="btnMD3"
ShirtNumber="8"
KitColor="Crimson"
Surname="Gerrard"
Position="Attacking Midfielder"
Margin="25,25,0,0"/>
</WrapPanel>
<WrapPanel Name="panelStrikers" Grid.Column="0" Grid.Row="4">
<local:PlayerControl x:Name="btnST1"
ShirtNumber="9"
KitColor="Crimson"
Surname="Sturridge"
Position="The Future is bright"
Margin="0,25,25,0"/>
<local:PlayerControl x:Name="btnST2"
ShirtNumber="10"
KitColor="Crimson"
Surname="Rooney"
Position="Number 10" />
<local:PlayerControl x:Name="btnST3"
ShirtNumber="11"
KitColor="Crimson"
Surname="Welbeck"
Position="Striker"
Margin="25,25,0,0"/>
</WrapPanel>
</Grid>
</Window>
No comments:
Post a Comment