尝试设置自定义DependencyObject.显然缺少什么 [英] Trying to setup a custom DependencyObject. Clearly missing something

查看:100
本文介绍了尝试设置自定义DependencyObject.显然缺少什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在UWP应用程序中具有以下内容.请注意,我的Element来自DependencyObject,而不是Control,Panel等.但是,当我调用测试方法MessWithBindings()时,绑定不起作用.虽然会触发PropertyChanged方法,但是PropertyChangedEventHandler为null,所以它什么也不做.我是否应该以某种方式直接设置事件处理程序?还是我错过了另一个创建它的电话?

I have the following in a UWP app. Notice that my Element descends from DependencyObject, not from a Control, Panel, etc. But when I call the test method MessWithBindings(), the bindings are not working. The PropertyChanged method does fire, but the PropertyChangedEventHandler is null, so it doesn't do anything. Am I supposed to directly setup the event handler somehow? Or is there another call I'm missing that creates it?

顺便说一句,我有BindWidth/BindHeight方法的FrameworkElement版本,并且工作得很好.

Incidentally, I have FrameworkElement versions of the BindWidth/BindHeight methods, and those work just fine.

class WindowsElement: DependencyObject, INotifyPropertyChanged
{
    public WindowsElement()
    {
    }
    private double _Width { get; set; }
    private double _Height { get; set; }
    public double Width
    {
        get
        {
            return _Width;
        }
        set
        {
            if (_Width != value)
            {
                _Width = value;
                OnPropertyChanged("Width");
            }
        }
    }


    public double Height
    {
        get
        {
            return _Height;
        }
        set
        {
            if (_Height != value)
            {
                _Height = value;
                OnPropertyChanged("Height");
            }
        }
    }

    public static readonly DependencyProperty WidthProperty = DependencyProperty.Register(
        "Width",
        typeof(double),
        typeof(WindowsElement),
        null);

    public static readonly DependencyProperty HeightProperty = DependencyProperty.Register(
"Height",
typeof(double),
typeof(WindowsElement),
null);

    private double _ActualWidth { get; set; }

    public double ActualWidth {
        get
        {
            return _ActualWidth;
        }
        set
        {
            if (_ActualWidth != value)
            {
                _ActualWidth = value;
                OnPropertyChanged("ActualWidth");
            }
        }
    }

    private double _ActualHeight { get; set; }

    public double ActualHeight {
        get
        {
            return _ActualHeight;
        }
        set
        {
            if (_ActualHeight != value)
            {
                _ActualHeight = value;
                OnPropertyChanged("ActualHeight");
            }
        }
    }

    public static readonly DependencyProperty ActualWidthProperty = DependencyProperty.Register(
        "ActualWidth",
        typeof(double),
        typeof(WindowsElement),
        null);

    public static readonly DependencyProperty ActualHeightProperty = DependencyProperty.Register(
"ActualHeight",
typeof(double),
typeof(WindowsElement),
null);

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }

    internal void SetBinding(DependencyProperty property, Binding b)
    {
        BindingOperations.SetBinding(this, property, b);
    }

    public static void MessWithBindings()
    {
        WindowsElement we1 = new WindowsElement();
        WindowsElement we2 = new WindowsElement();
        we1.BindWidth(we2);
        we1.BindHeight(we2);
        we2.Width = 12;
        we2.ActualWidth = 13;
        we2.ActualHeight = 666;
        CommonDebug.LogLine(we1, we1.Width, we1.Height, we1.ActualWidth, we1.ActualHeight, we2, we2.ActualWidth, we2.ActualHeight);
        CommonDebug.DoNothing();
    }
}


internal static class WindowsElementAdditions
{
  public static void BindWidth(this WindowsElement bindMe, WindowsElement toMe)
  {
    Binding b = new Binding();
    b.Mode = BindingMode.OneWay;
    b.Source = toMe.ActualWidth;
    bindMe.SetBinding(WindowsElement.WidthProperty, b);
  }

  public static void BindHeight(this WindowsElement bindMe, WindowsElement toMe)
  {
    Binding b = new Binding();
    b.Mode = BindingMode.OneWay;
    b.Source = toMe.ActualHeight;
    bindMe.SetBinding(WindowsElement.HeightProperty, b);
  }
}

推荐答案

依赖项属性的属性包装器必须调用DependencyObject的GetValueSetValue方法,例如

The property wrapper of a dependency property must call the DependencyObject's GetValue and SetValue methods, e.g.

class WindowsElement : DependencyObject
{
    public static readonly DependencyProperty WidthProperty =
        DependencyProperty.Register(
            "Width", typeof(double), typeof(WindowsElement), null);

    public double Width
    {
        get { return (double)GetValue(WidthProperty); }
        set { SetValue(WidthProperty, value); }
    }
}

,它不得调用其他任何内容.当属性是由Binding(或Style Setter,还有一些其他来源)设置的时,框架不会调用属性包装器,而是直接调用SetValue.

and it must not call anything else than that. When the property is set by a Binding (or Style Setter, an a few other sources), the framework does not call the property wrapper, but directly calls SetValue.

为了获得内部有关更改的属性值的通知,该类应通过PropertyMetadata注册PropertyChangedCallback

In order to get internally notified about a changed property value, the class should register a PropertyChangedCallback via PropertyMetadata

public static readonly DependencyProperty WidthProperty =
    DependencyProperty.Register(
        "Width", typeof(double), typeof(WindowsElement),
        new PropertyMetadata((double)0, WidthPropertyChanged));

private static void WidthPropertyChanged(
    DependencyObject o, DependencyPropertyChangedEventArgs e)
{
    WindowsElement element = (WindowsElement)o;
    double width = (double)e.NewValue;
    // update element here if necessary
}


依赖项属性已经实现了一种机制,该机制可以通知侦听器(例如,绑定)有关更改后的属性值,因此在此无需实现INotifyPropertyChanged.

这篇关于尝试设置自定义DependencyObject.显然缺少什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆