将对象传递给 UserControl

问题描述 投票:0回答:2

我正在尝试创建一个可以向其传递“Person”对象的 CustomControl。如何将 person 对象传递给自定义控件,就像这样

PersonDetails="{Binding Path=Person}"
传递给 CusomControl ?

而不是通过

Address="{Binding Path=Person.Address}"Address="{Binding Path=Person.FirstName}"

wpf custom-controls
2个回答
1
投票

您必须将 PersonDetails 声明为 依赖属性

然后您可以将其用作任何其他 WPF 控件属性 - 在 XAML(包括数据绑定)和代码中。


0
投票

将对象传递

UserControl

有几个要求
  1. UserControl.xaml.cs
    • 依赖属性
    • 绑定属性
      • DependencyObject Getter
      • 依赖对象设置器
    • 构造函数中的InitializeComponent()
  2. UserControl.xaml
    • 标签中的DataContext属性
  3. MainWindow.xaml.cs
    • 公共属性用于获取和设置数据
    • 构造函数中的InitializeComponent()
  4. MainWindow.xaml
    • 标签中的Name属性
    • 标记中的
      Namespace 属性 将被消耗的UserControl
    • 使用 ElementName
    • 进行绑定

示例

在此示例中,

ColorList
是将由 MainWindow 使用的 UserControl
ColorInfo
模型用于演示与对象的数据绑定。

ColorInfo
型号

using 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
© www.soinside.com 2019 - 2024. All rights reserved.