gpt4 book ai didi

c# - 依赖属性数据上下文

转载 作者:行者123 更新时间:2023-11-30 20:22:47 26 4
gpt4 key购买 nike

我有一个用户控件,并为其设置了一个数据上下文。此用户控件还包含一个依赖属性。现在,我只想绑定(bind)到这个属性。

我认为问题与错误的数据上下文有关。

我的用户控件(称为 TimePicker)中的依赖属性如下所示:

public TimeSpan Time
{
get { return (TimeSpan)GetValue(TimeProperty); }
set
{
SetValue(TimeProperty, value);
OnPropertyChanged();
}
}

public static readonly DependencyProperty TimeProperty = DependencyProperty.Register("Time", typeof (TimeSpan), typeof (TimePicker));

我尝试这样使用它:

<upDownControlDevelopement:TimePicker Grid.Row="1" Time="{Binding Path=TimeValue}" />

当我这样做时,出现以下绑定(bind)错误:

System.Windows.Data Error: 40 : BindingExpression path error: 'TimeValue' property not found on 'object' ''TimePicker' (Name='TimePickerControl')'. BindingExpression:Path=TimeValue; DataItem='TimePicker' (Name='TimePickerControl'); target element is 'TimePicker' (Name='TimePickerControl'); target property is 'Time' (type 'TimeSpan')

非常感谢任何帮助

问候迈克尔

PS:代码可以在here下载

最佳答案

虽然现在这个问题已经解决了,但在我看来,似乎有一些地方对 DataContext 的使用不当。

在开发自定义可重用控件时,根本不应该设置 DataContextDataContext 是什么,由控件的用户决定,而不是开发人员。考虑以下常见的代码模式:

<Grid DataContext="{Binding Data}">
<TextBox Text="{Binding TextValue1}" />
<!-- Some more controls -->
</Grid>

请注意,您在这里使用的是 Grid 控件。控件的开发人员(在本例中为 WPF 团队)根本没有触及 DataContext - 这取决于您。作为控件开发人员,这对您意味着什么?您的 DependencyProperty 定义没问题,但您不应触及 DataContext。然后,您将如何将控件内的内容绑定(bind)到 DependencyProperty 值?一个好方法是使用模板(省略命名空间):

<MyTimePicker>
<MyTimePicker.Template>
<ControlTemplate TargetType="MyTimePicker">
<!-- Stuff in your control -->
<TextBlock Text="{TemplateBinding Time}" />
<TextBox Text="{Binding Time, RelativeSource={RelativeSource TemplatedParent}}" />
</ControlTemplate>
<MyTimePicker.Template>
</MyTimePicker>

请注意 TemplateBinding 总是单向的,所以如果您需要任何编辑,您需要使用普通绑定(bind)(如您在 TextBox 上看到的那样)在示例中)。

这仅意味着您控件内的 TextBlock/Box 将从您的自定义控件本身获取其 Time 值,忽略您可能已设置的任何 DataContext

然后,当您使用该控件时,您可以这样做(添加到我的第一个示例中):

<Grid DataContext="{Binding Data}">
<TextBox Text="{Binding TextValue1}" />
<!-- Some more controls -->
<MyTimePicker Time="{Binding TimeValue}" />
</Grid>

这里刚刚发生的是 MyTimePicker 根本没有在任何地方设置 DataContext - 它是从父控件(Grid).所以值是这样的:Data-->(binding)-->MyTimePicker.Time-->(template binding)-->TextBlock.Text

最重要的是,避免在自定义控件的构造函数中这样做:

public MyTimePicker()
{
InitializeComponent();
DataContext = this;
}

这将覆盖 XAML 中设置的任何 DataContext,这将使绑定(bind)变得非常痛苦(因为您必须始终手动设置 Source)。前面的例子行不通,这个也行不通:

<MyTimePicker DataContext="{Binding Data}" Time="{Binding TimeValue}" />

您可能认为这没问题,但是 DataContext 将在 InitializeComponent() 调用中解析,因此该值将立即被覆盖。因此,与 TimeValue 的绑定(bind)将改为在控件中查找它(当然会失败)。

只要在开发控件时不要触及 DataContext 就可以了。

关于c# - 依赖属性数据上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30476263/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com