[英]Setting a binding from code-behind in PropertyChangedCallback of a DependencyProperty
I'm trying to implement a UserControl
which hosts other controls which are bound to certain properties of it. 我正在尝试实现一个承载其他控件的UserControl
,这些控件绑定到它的某些属性。 In my case it'd display a Slider next to a NumericUpDown
- both controls would be bound to the UserControl
's Value
property. 在我的情况下,它将在NumericUpDown
旁边显示一个NumericUpDown
两个控件都将绑定到UserControl
的Value
属性。 My approach would be defining a DependencyProperty
for each control so when using this control, properties like Minimum
, TickPlacement
etc. can still be changed by setting a new slider as value for the corresponding property: 我的方法是为每个控件定义一个DependencyProperty
,因此当使用此控件时,仍可以通过将新的滑块设置为相应属性的值来更改属性Minimum
, TickPlacement
等。
<!-- Displays a slider with default properties next to a text block-->
<Foo/>
<!-- Displays a sider with custom properties -->
<Foo>
<Foo.Slider>
<Slider Maximum="500" TickPlacement="Both" TickFrequency="20"/>
</Foo.Slider>
</Foo>
The code-behind looks like this: 后面的代码如下所示:
public partial class Foo : UserControl
{
public Foo()
{
InitializeComponent();
Slider = new Slider();
}
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(nameof(Value), typeof(double), typeof(Foo), new PropertyMetadata(0.0));
public double Value
{
get => (double)GetValue(ValueProperty);
set => SetValue(ValueProperty, value);
}
public static readonly DependencyProperty SliderProperty = DependencyProperty.Register(nameof(Slider), typeof(Slider), typeof(Foo),
new PropertyMetadata(
new PropertyChangedCallback((obj, e) =>
{
Slider slNew = (Slider)e.NewValue;
if (slNew == null)
obj.SetValue(SliderProperty, new Slider());
else
slNew.SetBinding(ValueProperty,
new Binding("Value")
{
Source = obj,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
Mode = BindingMode.TwoWay
});
})));
public Slider Slider
{
get => (Slider)GetValue(SliderProperty);
set => SetValue(SliderProperty, value ?? new Slider());
}
}
The relevant part of the XAML code looks like this: XAML代码的相关部分如下所示:
<UserControl x:Name="ctrlBase" [...]>
<Grid [...]>
<Grid.ColumnDefinitions [...]/>
<ContentControl DataContext="{Binding ElementName=ctrlBase}"
Content="{Binding Path=Slider}"/>
<!-- NumericUpDown to be implemented -->
<TextBlock Grid.Column="1"
Text="{Binding ElementName=ctrlBase, Path=Value}/>
</Grid>
</UserControl>
The actual problem is that the binding created from code-behind doesn't seem to work. 实际的问题是从代码隐藏创建的绑定似乎不起作用。 I assume this due to the following: 我认为这是由于以下原因:
Value
property from XAML changes the value displayed by the text block but not the slider's value. 从XAML更改Value
属性会更改文本块显示的值,但不会更改滑块的值。 You're using the wrong ValueProperty
. 您使用了错误的ValueProperty
。 It should be the one of the Slider class, not Foo.ValueProperty
: 它应该是Slider类之一,而不是Foo.ValueProperty
:
slNew.SetBinding(Slider.ValueProperty, new Binding("Value") { ... });
It would have worked if you had used Slider.ValueProperty.AddOwner
instead of DependencyProperty.Register
. 如果您使用的是Slider.ValueProperty.AddOwner
而不是DependencyProperty.Register
那将会起作用。
That said, a simpler approach would probably be to simply declare a Slider in your UserControl's XAML and provide a default Slider Style in the Foo Resources during instantiation: 也就是说,一种更简单的方法可能是在实例化期间在UserControl的XAML中声明一个Slider并在Foo Resources中提供默认的Slider Style:
<Foo ...>
<Foo.Resources>
<Style TargetType="Slider">
...
</Style>
</Foo.Resources>
</Foo>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.