简体   繁体   English

从DependencyProperty的PropertyChangedCallback中的代码后面设置绑定

[英]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两个控件都将绑定到UserControlValue属性。 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 ,因此当使用此控件时,仍可以通过将新的滑块设置为相应属性的值来更改属性MinimumTickPlacement等。

<!-- 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: 我认为这是由于以下原因:

  1. Moving the slider won't change the value displayed by the text block next to the slider. 移动滑块不会更改滑块旁边的文本块显示的值。
  2. Changing the 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM