带有许多控件的WPF UserControl - 如何创建映射到许多控件的依赖项属性?

mar*_*mnl 3 wpf xaml binding wpf-controls

我已经成功创建了一个带有Depedency属性的UserControl,允许我绑定到UserControl中的单个TextBox.但是,当我在UserControl中有许多控件并且只想绑定到单个属性(根据许多控件中的值构建)时,我不确定如何执行此操作?

UserControl有3个文本框,用于年,月和日期我想将它绑定到单个Date属性,到目前为止,我有这个:

<UserControl x:Class="MyApp.DateControl"...>
<StackPanel>
    <StackPanel Orientation="Horizontal">
        <TextBox Name="textbox_year" />
        <TextBox Name="textbox_month" />
        <TextBox Name="textbox_day" />
    </StackPanel>
</StackPanel>
</UserControl>
Run Code Online (Sandbox Code Playgroud)

我需要在后面的代码中添加什么来使Date属性从三个文本框中获取,所以在使用我的控件的另一个容器中可以绑定到Date.我意识到,因为我的UserControl是目标,我必须创建一个依赖属性,但它似乎很复杂..

public partial class DateControl : UserControl
{
    public DateControl()
    {
        InitializeComponent();
    }

    public DateTime Date
    {
        get
        {
            DateTime dt;
            if (DateTime.TryParseExact(String.Format("{0}-{1}-{2}", this.textbox_year.Text, this.textbox_month.Text, this.textbox_day.Text), "yyyy-MM-dd", null, System.Globalization.DateTimeStyles.None, out dt))
                return dt;
            else
                return DateTime.MinValue;
        }
    }
Run Code Online (Sandbox Code Playgroud)

Pav*_*kov 6

我建议使用转换器来达到你想要的效果.

您的用户控件的XAML将如下所示:

<UserControl x:Class="MyDateControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:my="clr-namespace:MyDateControl"
             x:Name="root">
    <UserControl.Resources>
        <my:DatePartConverter x:Key="DatePartConverter"
                              Date="{Binding ElementName=root, Path=Date}"/>
    </UserControl.Resources>

    <StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBox Name="textbox_year" Text="{Binding ElementName=root, Path=Date, Converter={StaticResource DatePartConverter}, ConverterParameter=year, Mode=TwoWay}"/>
            <TextBox Name="textbox_month" Text="{Binding ElementName=root, Path=Date, Converter={StaticResource DatePartConverter}, ConverterParameter=month, Mode=TwoWay}" />
            <TextBox Name="textbox_day" Text="{Binding ElementName=root, Path=Date, Converter={StaticResource DatePartConverter}, ConverterParameter=day, Mode=TwoWay}" />
        </StackPanel>
    </StackPanel>
</UserControl>
Run Code Online (Sandbox Code Playgroud)

在代码隐藏中,您将只拥有依赖属性:

public DateTime Date {
   get { return (DateTime)GetValue(DateProperty); }
   set { SetValue(DateProperty, value); }
}

public static readonly DependencyProperty DateProperty = 
   DependencyProperty.Register("Date", typeof(DateTime), typeof(MyDateControl), 
      new FrameworkPropertyMetadata(DateTime.Now, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
Run Code Online (Sandbox Code Playgroud)

转换器看起来像这样:

public class DatePartConverter : Freezable, IValueConverter
{
    public DateTime Date {
        get { return (DateTime)GetValue(DateProperty); }
        set { SetValue(DateProperty, value); }
    }

    public static readonly DependencyProperty DateProperty =
        DependencyProperty.Register("Date", typeof(DateTime), typeof(DatePartConverter), new UIPropertyMetadata(DateTime.Now));


    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        DateTime date = (DateTime)value;
        string datePartType = (string)parameter;

        string result;

        switch (datePartType) {
            case "year":
                result = date.Year.ToString().PadLeft(4, '0');
                break;
            case "month":
                result = date.Month.ToString().PadLeft(2, '0');
                break;
            case "day":
                result = date.Day.ToString().PadLeft(2, '0');
                break;
            default:
                throw new InvalidOperationException("Unknown date part type (ConverterParameter)");
        }

        return result;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        string datePartValue = (string)value;
        string datePartType = (string)parameter;

        DateTime result;

        switch (datePartType) {
            case "year":
                result = new DateTime(int.Parse(datePartValue), Date.Month, Date.Day);
                break;
            case "month":
                result = new DateTime(Date.Year, int.Parse(datePartValue), Date.Day);
                break;
            case "day":
                result = new DateTime(Date.Year, Date.Month, int.Parse(datePartValue));
                break;
            default:
                throw new InvalidOperationException("Unknown date part type (ConverterParameter)");
        }

        return result;
    }

    protected override Freezable CreateInstanceCore() {
        return new DatePartConverter();
    }
}
Run Code Online (Sandbox Code Playgroud)