更新 DependencyProperty setter 中的 UserControl 子项不起作用
Updating UserControl children in DependencyProperty setter not working
我的 Silverlight 应用程序中有一个 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 User Control")
<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;
}
}
}
}
使用了项目的其余部分 "as is",即没有更改编译器选项,还保留了服务器部分 "as is"。
观察:
- 我看到
Vm.HeaderText
的 getter 在绑定期间被调用
操作,但从未调用 DependencyProperty
MyCtrl.HeaderText
的 setter。
- 自定义控件下方MainPage中的TextBlock正确显示绑定值。
- 没有编译器警告。
- 没有抛出异常。
- 应用程序运行时没有调试输出。
这感觉就像一些重要的事情在它不应该发生的地方默默地失败了。
好吧,您似乎无法更新 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;
}
也许我可以阐明您的观察和假设:
您可以更新DependencyProperty
setter中的子控件。调用您的 setter 并亲自查看,将执行更新。您错误地假设绑定引擎有义务调用您的 setter。好吧,它只是在您的控件上调用 SetValue(HeaderTextProperty, newValue);
,无需调用 setter.
您的观察是特定行为。
如您所知,正确的方法是使用 属性Changed 回调。
你的viewmodel Vm.HeaderText
上的属性 getter被绑定引擎调用了,因为你的viewmodel没有DependencyObject
而且HeaderText没有DependencyProperty
所以没有 SetValue(...)
也没有 GetValue(...)
您看不到任何编译器警告或异常,也没有任何静默失败,因为您的场景没有任何问题。
我的 Silverlight 应用程序中有一个 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 User Control")
<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;
}
}
}
}
使用了项目的其余部分 "as is",即没有更改编译器选项,还保留了服务器部分 "as is"。
观察:
- 我看到
Vm.HeaderText
的 getter 在绑定期间被调用 操作,但从未调用DependencyProperty
MyCtrl.HeaderText
的 setter。 - 自定义控件下方MainPage中的TextBlock正确显示绑定值。
- 没有编译器警告。
- 没有抛出异常。
- 应用程序运行时没有调试输出。
这感觉就像一些重要的事情在它不应该发生的地方默默地失败了。
好吧,您似乎无法更新 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;
}
也许我可以阐明您的观察和假设:
您可以更新
DependencyProperty
setter中的子控件。调用您的 setter 并亲自查看,将执行更新。您错误地假设绑定引擎有义务调用您的 setter。好吧,它只是在您的控件上调用SetValue(HeaderTextProperty, newValue);
,无需调用 setter.您的观察是特定行为。
如您所知,正确的方法是使用 属性Changed 回调。
你的viewmodel
Vm.HeaderText
上的属性 getter被绑定引擎调用了,因为你的viewmodel没有DependencyObject
而且HeaderText没有DependencyProperty
所以没有SetValue(...)
也没有GetValue(...)
您看不到任何编译器警告或异常,也没有任何静默失败,因为您的场景没有任何问题。