Reputation: 87
I'm trying to create a CustomControl to which I can pass an "Person" object. How can I pass the person object to the custom control like this PersonDetails="{Binding Path=Person}"
to the CusomControl ?
instead of passing Address="{Binding Path=Person.Address}"Address="{Binding Path=Person.FirstName}"
ect
Upvotes: 3
Views: 2805
Reputation: 626
There are several requirements to pass an object to a UserControl
UserControl.xaml.cs
UserControl.xaml
MainWindow.xaml.cs
MainWindow.xaml
In this example,
ColorList
is the UserControl that will be consumed by the MainWindow. TheColorInfo
model is used for demonstrating data binding with an object.Project Structure
GitHub Repository
ColorInfo
Modelusing System.Windows.Media;
namespace WpfProject.Models;
public class ColorInfo
{
public string Name { get; set; } = string.Empty;
public SolidColorBrush Value { get; set; } = default!;
}
ColorList.xaml.cs
using System.Windows;
using System.Windows.Controls;
using WpfProject.Models;
namespace WpfProject.UserControls;
public partial class ColorList : UserControl
{
// ✶ Binding Dependency Property
public static readonly DependencyProperty ColorsProperty =
DependencyProperty.Register(
name: nameof(Colors), // The "Name" of the property to register
propertyType: typeof(IEnumerable<ColorInfo>), // The "Type" of the property to register
ownerType: typeof(ColorList), // The "Type" of object that owns the property to register
typeMetadata: new FrameworkPropertyMetadata(
defaultValue: Enumerable.Empty<ColorInfo>(),
flags: FrameworkPropertyMetadataOptions.None
)
);
// ✶ Binding Property
public IEnumerable<ColorInfo> Colors
{
get => (IEnumerable<ColorInfo>)GetValue(ColorsProperty); // ✶ Binding Getter
set => SetValue(ColorsProperty, value); // ✶ Binding Setter
}
public ColorList()
{
InitializeComponent();
}
}
ColorList.xaml
<UserControl
x:Class="WpfProject.UserControls.ColorList"
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:WpfProject"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
>
<ListBox Name="ColorsListBox" ItemsSource="{Binding Path=Colors}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<Rectangle Width="23" Height="23">
<Rectangle.Fill>
<SolidColorBrush Color="{Binding Path=Value.Color}" />
</Rectangle.Fill>
</Rectangle>
<TextBlock
Text="{Binding Path=Value}"
FontFamily="Consolas"
FontSize="16"
VerticalAlignment="Center"
Margin="5 0 0 0" />
<TextBlock
Text="{Binding Path=Name}"
FontFamily="Consolas"
FontSize="16"
FontWeight="Bold"
VerticalAlignment="Center"
Margin="5 0 0 0" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</UserControl>
MainWindow.xaml.cs
using System.Windows;
using System.Windows.Media;
using WpfProject.Models;
namespace WpfProject;
public partial class MainWindow : Window
{
public IEnumerable<ColorInfo> Colors => typeof(Brushes)
.GetProperties()
.Where(info => info.PropertyType == typeof(SolidColorBrush))
.Select(info =>
new ColorInfo()
{
Name = info.Name,
Value = (SolidColorBrush)info.GetValue(info, null)!
}
).ToList()! ?? Enumerable.Empty<ColorInfo>();
public MainWindow()
{
InitializeComponent();
}
}
MainWindow.xaml
<Window
Name="Main"
x:Class="WpfProject.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:WpfProject"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800"
xmlns:UserControls="clr-namespace:WpfProject.UserControls"
>
<Grid>
<UserControls:ColorList Colors="{Binding ElementName=Main, Path=Colors}" />
</Grid>
</Window>
📃 ColorList.xaml.cs
✅ public static readonly DependencyProperty // For registering Colors
✅ public IEnumerable<ColorInfo> Colors // Implements DependencyObject GetValue and SetValue
✅ InitializeComponent(); // In the constructor
📃 ColorList.xaml
// Set the "Data Context" of the "User Control" to itself (The code behind)
// This is the equivalent of calling DataContext = this; in the constructor
// in the code behind
✅ <UserControl DataContext="{Binding RelativeSource={RelativeSource Self}}" ...
📃 MainWindow.xaml.cs
✅ public IEnumerable<ColorInfo> Colors // This is the property that is "passed" to the user control
✅ InitializeComponent(); // In the constructor
📃 MainWindow.xaml
✅ <Window Name="Main" ... // This is used as the ElementName in the data binding
✅ <Window xmlns:UserControls="clr-namespace:WpfProject.UserControls" ... // Registers the user control in the xaml
✅ <UserControls:ColorList Colors="{Binding ElementName=Main, Path=Colors}" /> // Use "ElementName" for binding
Upvotes: 0
Reputation: 17272
You have to declare PersonDetails as a dependency property.
Then you can use it as any other WPF control property - both in XAML (including data binding) and in code.
Upvotes: 1