【问题标题】:Setting a binding from code-behind in PropertyChangedCallback of a DependencyProperty在 DependencyProperty 的 PropertyChangedCallback 中从代码隐藏设置绑定
【发布时间】:2018-08-15 13:13:42
【问题描述】:

我正在尝试实现一个UserControl,它承载了绑定到它的某些属性的其他控件。在我的例子中,它会在NumericUpDown 旁边显示一个滑块——两个控件都将绑定到UserControl 的Value 属性。我的方法是为每个控件定义一个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>

代码隐藏如下:

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());
    }
}

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>

实际的问题是从代码隐藏创建的绑定似乎不起作用。我认为这是由于以下原因:

  1. 移动滑块不会改变文本块显示的值 滑块旁边。
  2. 从 XAML 更改中更改 Value 属性 文本块显示的值,但不是滑块的值。

【问题讨论】:

    标签: c# wpf binding dependency-properties code-behind


    【解决方案1】:

    您使用了错误的ValueProperty。它应该是 Slider 类之一,而不是Foo.ValueProperty:

    slNew.SetBinding(Slider.ValueProperty, new Binding("Value") { ... });
    

    如果您使用 Slider.ValueProperty.AddOwner 而不是 DependencyProperty.Register,它会起作用。


    也就是说,一种更简单的方法可能是简单地在 UserControl 的 XAML 中声明一个 Slider,并在实例化期间在 Foo 资源中提供默认的 Slider 样式:

    <Foo ...>
        <Foo.Resources>
            <Style TargetType="Slider">
                ...
            </Style>
        </Foo.Resources>
    </Foo>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-08
      • 2015-12-30
      相关资源
      最近更新 更多