如何在WPF中创建可绑定属性?

7

我有一个用户控件。我想在我的用户控件中创建一个可绑定属性。我按照以下方式创建了一个DependencyProperty:

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

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

我随后在XAML中使用它:
<ctrls:DaiesContainer  Date="{Binding Date, Mode=OneWay}"/>

在我的ViewModel中,调用了Date属性的get方法。但是在我的用户控件中,Date属性并没有被设置为一个值。

你在XAML中插入DateTime时,是否使用了兼容的模式 - Ibrahim Najjar
你如何知道属性没有被设置?你没有在依赖属性的元数据中注册PropertyChangedCallback。请注意,当属性在XAML中设置时,CLR包装器的setter不会被调用,详见 这里 - Clemens
@Clemens 谢谢,很好,但我必须调用非静态方法。 - Ali Jalali
3个回答

11

你的依赖属性实现缺少一个 PropertyChangedCallback,当属性值更改时会调用该回调。该回调被注册为静态方法,它将当前实例(在其上更改了属性的实例)作为第一个参数(类型为DependencyObject)传递。你需要将其转换为你的类类型以访问实例字段或方法,如下所示。

public static readonly DependencyProperty DateProperty =
    DependencyProperty.Register("Date", typeof(DateTime), typeof(DaiesContainer),
    new PropertyMetadata(DateTime.Now, DatePropertyChanged));

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

private void DatePropertyChanged(DateTime date)
{
    //...
}

private static void DatePropertyChanged(
    DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    ((DaiesContainer)d).DatePropertyChanged((DateTime)e.NewValue);
}
请注意,为依赖属性设置默认值仅在类的所有实例中执行一次。将值设置为DateTime.Now将为它们所有产生相同的默认值,即注册静态DependencyProperty的时间。我想使用更有意义的值,例如DateTime.MinValue,可能是一个更好的选择。由于MinValue已经是新创建的DateTime实例的默认值,因此您甚至可以省略属性元数据中的默认值:
public static readonly DependencyProperty DateProperty =
    DependencyProperty.Register("Date", typeof(DateTime), typeof(DaiesContainer),
    new PropertyMetadata(DatePropertyChanged));

1
2020年建议:在依赖属性声明中使用“nameof(Date)”可以保护自己免于在更改属性名称后忘记更改此值。 - Anatoly Nikolaev
@AnatolyNikolaev 当然可以,但你不会在成千上万的旧答案中写下这个评论吧? - Clemens

0

将你的绑定模式设置为双向

<ctrls:DaiesContainer  Date="{Binding Date, Mode=TwoWay}"/>

在C#中,当我为日期属性设置一个值时,一切都很好,但是当我在XAML中为日期属性设置一个值时,它没有被设置。 - Ali Jalali

0

我认为你在 XAML UserControl 中有错误。

你应该通过 ElementName 进行绑定,例如:

<UserControl x:Class="WPFProject.DaiesContainer"
             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" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300"
             x:Name="daiesContainer">
    <Grid>
        <DatePicker SelectedDate="{Binding Date, ElementName=daiesContainer}" />
    </Grid>
</UserControl>

在这种情况下,您绑定到 DaiesContainer 类的 Date 属性。
如果您不使用 ElementName 进行绑定:
<DatePicker SelectedDate="{Binding Date}" />

UserControl DaiesContainer将尝试在该用户控件的DataContext中查找属性Date,如果未找到该属性,则将显示带有空选定值的DatePicker


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接