在DependencyProperty setter中更新UserControl子组件不工作
本文关键字:组件 工作 UserControl 更新 DependencyProperty setter | 更新日期: 2023-09-27 18:10:36
我在Silverlight应用程序中有一个UserControl,由于某种原因,如果我将UserControl绑定到视图模型中的值,则UserControl的DependencyProperty没有设置。我花了几个小时以试错的方式调试,现在我完全不知道下一步要尝试什么。
我可以用
在新的Silverlight项目中重现这个问题MainPage.xaml
<UserControl x:Class="SilverlightApplication1.MainPage"
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:SilverlightApplication1"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel>
<local:MyCtrl HeaderText="{Binding HeaderText}"/>
<TextBlock Text="{Binding HeaderText}"/>
</StackPanel>
</Grid>
</UserControl>
MainPage.xaml.cs
using System.Windows.Controls;
namespace SilverlightApplication1
{
public class Vm
{
public string HeaderText
{ get; set; }
}
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
DataContext = new Vm() { HeaderText = "My Header" };
}
}
}
MyCtrl。xaml(作为新的"Silverlight用户控件"添加)
<UserControl x:Class="SilverlightApplication1.MyCtrl"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<TextBlock x:Name="txtHeader" />
</Grid>
</UserControl>
MyCtrl.xaml.cs
using System.Windows;
using System.Windows.Controls;
namespace SilverlightApplication1
{
public partial class MyCtrl : UserControl
{
public MyCtrl()
{
InitializeComponent();
}
public static readonly DependencyProperty HeaderTextProperty = DependencyProperty.Register(
"HeaderText", typeof(string), typeof(MyCtrl), null);
public string HeaderText
{
get { return (string)GetValue(HeaderTextProperty); }
set
{
// NEVER CALLED
SetValue(HeaderTextProperty, value);
this.txtHeader.Text = value;
}
}
}
}
项目的其余部分使用"原样",即没有更改编译器选项,服务器部分也保留"原样"。
观察:
- 我看到
Vm.HeaderText
的getter在绑定期间被调用操作,但DependencyProperty
MyCtrl.HeaderText
的setter永远不会被调用。 - MainPage中自定义控件下方的TextBlock正确显示绑定值。
- 没有编译警告。
- 没有抛出异常。
- 应用程序运行时没有调试输出。
这感觉就像一些重要的东西在它不应该的地方无声地失败了。
也许我可以对你的观察和假设提供一些启发:
-
可以更新
DependencyProperty
setter中的子控件。调用setter并亲自查看,更新将被执行。您错误地认为绑定引擎必须调用setter。嗯,它只调用控件的SetValue(HeaderTextProperty, newValue);
,不需要调用setter。 -
你的观察是指定行为
-
正如你所发现的,正确的方法是使用propertyChanged回调。
-
视图模型
Vm.HeaderText
上的属性getter由绑定引擎调用,因为视图模型没有DependencyObject
, HeaderText没有DependencyProperty
,所以没有SetValue(...)
和GetValue(...)
-
您看不到任何编译器警告或异常,也没有任何静默失败,因为您的场景没有任何问题。
嗯,似乎你不能更新一个DependencyProperty setter内的子控件(将是有趣的知道为什么,如果这是指定的行为…)
public static readonly DependencyProperty HeaderTextProperty = DependencyProperty.Register(
"HeaderText", typeof(string), typeof(MyCtrl), new PropertyMetaData(OnHeaderTextChanged));
public string HeaderText
{
get { return (string)GetValue(HeaderTextProperty); }
set { SetValue(HeaderTextProperty, value); }
}
private static void OnHeaderTextChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var ctrl = d as MyCtrl;
ctrl.txtHeader.Text = (string)e.NewValue;
}