【问题标题】:DependencyProperty fails to update window datacontextDependencyProperty 无法更新窗口数据上下文
【发布时间】:2013-07-23 13:33:56
【问题描述】:

我在具有依赖属性的用户控件和我有一个自定义类作为数据上下文中的模型的窗口之间存在半工作绑定的不良情况。

我的窗口

<src:BaseWindow x:Class="Levscan.Wpf.Controls.DialogWindows.SystemSettingsDialog"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:src="clr-namespace:Levscan.Wpf.Controls.Abstract"
    xmlns:ctrl_io="clr-namespace:Levscan.Wpf.Controls.Controls.IO"
    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">

    <ctrl_io:DirectoryBrowser Width="250" SelectedPath="{Binding Path=PathInbox, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"/>
</src:BaseWindow>

我的用户控件

<UserControl Name="DirectoryBrowserUC" x:Class="Levscan.Wpf.Controls.Controls.IO.DirectoryBrowser"
         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="53" d:DesignWidth="392">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="8*" />
        <ColumnDefinition Width="2*" />
    </Grid.ColumnDefinitions>

    <TextBox Text="{Binding ElementName=DirectoryBrowserUC, Path=SelectedPath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" Style="{StaticResource TextBoxInError}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Grid.Column="0" Margin="5,0" />
    <Button Margin="5,0" Content="..." Grid.Column="1" Click="OnBrowse_Click" />
</Grid>

我的用户控件 - 隐藏代码

public partial class DirectoryBrowser : UserControl
{
    public static readonly DependencyProperty SelectedPathProperty =
        DependencyProperty.Register("SelectedPath", typeof(string), typeof(DirectoryBrowser));
    public string SelectedPath
    {
        get { return this.GetValue(SelectedPathProperty) as string; }
        set { this.SetValue(SelectedPathProperty, value); }
    }
}

当我启动我的窗口时,我加载了一个继承 INotifyPropertyChanged 接口的自定义类。 设置新数据时,我的属性会执行 NotifyPropertyChanged()。

当我在用户控件中启动我的文本框时,我的窗口中的数据和窗口 DataContext 中的自定义类会更新(到目前为止一切都很好)。

但是我注意到,当我直接编辑文本框(输入新文本)或使用它旁边的按钮并使用 windows 目录对话框选择新路径时,我在 DataContext 中的属性没有更新。

我尝试了各种绑定变体,但没有任何效果,要么没有加载数据,要么我无法更改值。

我怀疑我的绑定在某个地方有点偏离。

更新

似乎我在上面的代码中需要的只是在控件的窗口上的绑定上添加 Mode=TwoWay。由于我换掉了东西并添加了我从未注意到这是唯一缺少的东西,所以当我真正拥有它时,其他东西就消失了。

【问题讨论】:

  • 您是否尝试将依赖属性中的 propertychanged 事件处理程序和虚拟转换器添加到您的绑定中,以验证绑定是否正常工作并通知值更改?是否有模型的多个实例(绑定到您使用的之外的其他东西)。
  • 在我的 Dependency 属性声明中添加了 PropertyChangedCallback。当我的模型加载并且当我编辑它被调用的字段时。但是当我在 Windows DataContext 中访问我的属性时,它仍然是相同的旧值。

标签: c# wpf xaml data-binding wpf-controls


【解决方案1】:

在 SelectedPath 的绑定中添加 Mode=TwoWay。自定义依赖属性的默认绑定模式是 OneWay。

这并不神奇。首先,依赖属性有一个默认绑定模式。当您编写自己的依赖属性时,默认的“默认绑定模式”是 OneWay,您可以按照 Clemens 的建议将其覆盖为 TwoWay。如果没有在用户控件级别指定绑定模式,WPF 将使用默认的绑定模式,即 OneWay。这就解释了为什么数据上下文没有得到更新。

第二种绑定方式是在目标上定义的,而不是在源上定义的,所以无论SelectedPath上的默认绑定方式是什么,它都会从TextBox中更新,因为Text属性的默认绑定方式是双向绑定(失去焦点)。

一句话。只需在用户控件级别显式添加双向绑定或覆盖 FrameworkPropertyMetadata 并默认提供双向绑定即可解决您的问题。

【讨论】:

  • +1 或将BindsTwoWayByDefault 设置为property metadata options
  • 用户控件中已绑定 selectedpath 的文本框有 Mode=TwoWay。我也试过在windows的用户控件绑定上添加Mode=TwoWay,没有任何变化。
  • 当我在两个绑定(窗口中的控件和用户控件中的文本框)上添加 Mode=TwoWay 时,它现在神奇地工作了。我上次尝试时一定有其他绑定。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-29
  • 1970-01-01
  • 2012-10-15
  • 1970-01-01
  • 2013-03-10
  • 2019-09-11
  • 1970-01-01
相关资源
最近更新 更多