简体   繁体   English

为什么不能绑定到此依赖项属性?

[英]Why can't I bind to this dependency property?

I don't understand why I can't bind my custom width dependency property (of my custom control) to another custom control dependency property. 我不明白为什么我不能将(自定义控件的) 自定义宽度依赖属性绑定到另一个自定义控件依赖属性。

I followed all guidelines I'm quite sure dependency properties are well implemented. 我遵循所有准则,我确信依赖项属性已正确实现。

Both Window (BlackAndWhiteWindow), Canvas (all of them are custom controls, not those from wpf) inherits from control. Window(BlackAndWhiteWindow),Canvas(它们都是自定义控件 ,而不是来自wpf的控件)都继承自控件。

Any suggestion? 有什么建议吗? I'm going mad... 我要疯了...

Visual studio error states that is impossible to bind the property because you can only bind a dependency property to a dependency object, but they are dependency objects and i'm binding to dependency properties!! Visual Studio错误指出不可能绑定该属性,因为您只能将一个依赖项属性绑定到一个依赖项对象,但是它们是依赖项对象,而我正在绑定到依赖项属性!

EDIT 1: 编辑1:

XAML XAML

<test:BlackAndWhiteWindow x:Class="GSdk.TestGsdkShared.TestWindow" x:Name="bwWindow"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:windows="urn:gsdk-net"
             xmlns:test="clr-namespace:GSdk.TestGsdkShared"
             mc:Ignorable="d"
             Width="320" Height="240"
             d:DesignHeight="300" d:DesignWidth="300">
    <windows:Canvas Width="{Binding ElementName=bwWindow, Path=Width}" Height="100">
    </windows:Canvas>
</test:BlackAndWhiteWindow>

Control class 控制等级

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using GSdk.Net.Lglcd;
using System.Windows;
using System.Windows.Markup;
using System.Xaml;
using GSdk.Shared.Windows.Properties;

namespace GSdk.Shared.Windows
{
    public class Control : DependencyObject, IDisposable
    {
        private volatile bool m_Disposing;

        public Control()
        {
            /*Font = new Font(
                "monospace",
                12.0f,
                System.Drawing.FontStyle.Bold
            );*/
        }

        public static Property<Font> FontProperty = new Property<ContentControl, Font>(c => c.Font, new FrameworkPropertyMetadata(new Font("monospace", 12.0f, System.Drawing.FontStyle.Bold), FrameworkPropertyMetadataOptions.Inherits));
        public static Property<int> WidthProperty = new Property<ContentControl, int>(c => c.Width, new FrameworkPropertyMetadata(1, FrameworkPropertyMetadataOptions.Inherits));
        public static Property<int> HeightProperty = new Property<ContentControl, int>(c => c.Height, new FrameworkPropertyMetadata(1, FrameworkPropertyMetadataOptions.Inherits));

        public Font Font
        {
            get { return FontProperty[this]; }
            set
            {
                if (Font != null && Font != value)
                    Font.Dispose();
                FontProperty[this] = value;
            }
        }
        public int Width { get { return WidthProperty[this]; } set { WidthProperty[this] = value; } }
        public int Height { get { return HeightProperty[this]; } set { HeightProperty[this] = value; } }
        public virtual DeviceTypes DeviceType { get { return DeviceTypes.Invalid; } }
        public bool Disposing { get { return m_Disposing; } protected set { m_Disposing = value; } }

        #region Dispose handling
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            Disposing = true;
            if (disposing)
            {
                // Managed resources
            }

            // Unmanaged resources
            try
            {
                if (Font != null) Font.Dispose();
            }
            catch { }
        }

        ~Control()
        {
            Dispose(false);
        }
        #endregion
    }
}

Canvas class 帆布类

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using GSdk.Net.Lglcd;
using System.Windows;
using System.Windows.Markup;
using System.Xaml;
using GSdk.Shared.Windows.Properties;

namespace GSdk.Shared.Windows
{
    public class Canvas : Layout, IDrawable
    {
        public Canvas()
            : base()
        {
        }

        public static Property<int> TopProperty = new AttachedProperty<Canvas, int>(() => TopProperty, new FrameworkPropertyMetadata(default(int), FrameworkPropertyMetadataOptions.Inherits));
        public static Property<int> LeftProperty = new AttachedProperty<Canvas, int>(() => LeftProperty, new FrameworkPropertyMetadata(default(int), FrameworkPropertyMetadataOptions.Inherits));
        public static Property<int> BottomProperty = new AttachedProperty<Canvas, int>(() => BottomProperty, new FrameworkPropertyMetadata(default(int), FrameworkPropertyMetadataOptions.Inherits));
        public static Property<int> RightProperty = new AttachedProperty<Canvas, int>(() => RightProperty, new FrameworkPropertyMetadata(default(int), FrameworkPropertyMetadataOptions.Inherits));

        public static void SetTop(DependencyObject obj, int value)
        {
            obj.SetValue(TopProperty, value);
        }
        public static int GetTop(DependencyObject obj)
        {
            return (int)obj.GetValue(TopProperty);
        }
        public static bool IsSetTop(DependencyObject obj)
        {
            return ((int)obj.GetValue(TopProperty) != default(int));
        }

        public static void SetLeft(DependencyObject obj, int value)
        {
            obj.SetValue(LeftProperty, value);
        }
        public static int GetLeft(DependencyObject obj)
        {
            return (int)obj.GetValue(LeftProperty);
        }
        public static bool IsSetLeft(DependencyObject obj)
        {
            return ((int)obj.GetValue(LeftProperty) != default(int));
        }

        public static void SetBottom(DependencyObject obj, int value)
        {
            obj.SetValue(BottomProperty, value);
        }
        public static int GetBottom(DependencyObject obj)
        {
            return (int)obj.GetValue(BottomProperty);
        }
        public static bool IsSetBottom(DependencyObject obj)
        {
            return ((int)obj.GetValue(BottomProperty) != default(int));
        }

        public static void SetRight(DependencyObject obj, int value)
        {
            obj.SetValue(RightProperty, value);
        }
        public static int GetRight(DependencyObject obj)
        {
            return (int)obj.GetValue(RightProperty);
        }
        public static bool IsSetRight(DependencyObject obj)
        {
            return ((int)obj.GetValue(RightProperty) != default(int));
        }

        public Bitmap Draw()
        {
            // FIXME: This should be changed, is temporary
            //MessageBox.Show(Width.ToString() + " " + Height.ToString());
            Bitmap tmp = new Bitmap(Width, Height);
            using (Graphics g = Graphics.FromImage(tmp))
            {
                g.FillRectangle(Brushes.AliceBlue, 0, 0, Width, Height);
                foreach (var item in Items)
                {
                    int x, y;
                    x = y = 0;
                    IDrawable drawableItem = item as IDrawable;
                    DependencyObject dependencyItem = item as DependencyObject;

                    if (dependencyItem != null && drawableItem != null)
                    {
                        if (IsSetTop(dependencyItem))
                            y = GetTop(dependencyItem);
                        else if (IsSetBottom(dependencyItem))
                            y = Height - GetBottom(dependencyItem);

                        if (IsSetLeft(dependencyItem))
                            x = GetLeft(dependencyItem);
                        else if (IsSetRight(dependencyItem))
                            x = Width - GetRight(dependencyItem);
                        g.DrawImage(drawableItem.Draw(), x, y);
                    }
                }
            }
            return tmp;
        }
    }
}

Window class 窗类

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using GSdk.Net.Lglcd;
using System.Windows;
using System.Windows.Markup;
using System.Xaml;
using GSdk.Shared.Windows.Properties;
using System.ComponentModel;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;

namespace GSdk.Shared.Windows
{
    public abstract class Window : ContentControl, IDrawable
    {
        private Action m_DispatcherDrawHandler;
        private Thread m_DrawThread;
        private Bitmap Background = QvgaDevice.CreateValidBitmap();

        public Window(Applet applet = null)
        {
            m_DispatcherDrawHandler = new Action(DispatcherDrawHandler);
            if (DesignerProperties.GetIsInDesignMode(this))
            {
                Applet = new Applet()
                {
                    Autostartable = false,
                    SupportedDevices = DeviceType,
                    Name = GetType().FullName,
                };
                Applet.Connect();
                Applet.GetDevices<DefaultDeviceCollection>().Qvga.ForegroundApplet = true;
                Applet.GetDevices<DefaultDeviceCollection>().Qvga.AppletPriority = AppletPriorities.Alert;

                m_DrawThread = new Thread(new ThreadStart(DrawHandler));
                m_DrawThread.Start();
                //Dispatcher.Hooks.DispatcherInactive += new EventHandler(Hooks_DispatcherInactive);
            }
            else
            {
                Applet = applet ?? CreateApplet();
                //if (Applet == null) throw new NullReferenceException("CreateApplet() must return a not null value");
            }
        }

        private void DispatcherDrawHandler()
        {
            Applet.GetDevices<DefaultDeviceCollection>().Qvga.Update(Draw());
        }

        private void DrawHandler()
        {
            while (!Disposing)
            {
                Dispatcher.Invoke(m_DispatcherDrawHandler);
                Thread.Sleep(33);
            }
        }

        /*private void Hooks_DispatcherInactive(object sender, EventArgs e)
        {
            Dispatcher.Invoke(new Action(() =>
            {
            }));
        }*/

        protected abstract Applet CreateApplet();

        //public readonly object SyncRoot = new object();
        public Applet Applet { get; private set; }
        public override DeviceTypes DeviceType { get { return DeviceTypes.Qvga; } }

        public virtual Bitmap Draw()
        {
            using (Graphics g = Graphics.FromImage(Background))
            {
                g.FillRectangle(Brushes.Red, new Rectangle(0, 0, Background.Width, Background.Height));
                g.DrawString("Hello World", Font, Brushes.White, new PointF(0f, 0f));

                IDrawable ctrl = Content as IDrawable;
                if (ctrl != null)
                    g.DrawImage(ctrl.Draw(), 0, 0);
            }
            return Background;
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            lock (Applet)
                if (Applet != null) Applet.Dispose();
        }
    }
}

Property class 物业类别

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Windows;

namespace GSdk.Shared.Windows.Properties
{
    public struct Property<T>
    {
        Property(DependencyProperty prop)
        {
            m_DependencyProperty = prop;
        }

        readonly DependencyProperty m_DependencyProperty;

        public static implicit operator Property<T>(PropertyBase prop)
        {
            return new Property<T>(prop.DependencyProperty);
        }

        public static implicit operator DependencyProperty(Property<T> prop)
        {
            return prop.m_DependencyProperty;
        }

        public T this[DependencyObject obj]
        {
            get { return (T)obj.GetValue(m_DependencyProperty); }
            set { obj.SetValue(m_DependencyProperty, value); }
        }
    }

    public abstract class PropertyBase
    {
        public readonly DependencyProperty DependencyProperty;

        protected PropertyBase(DependencyProperty prop)
        {
            DependencyProperty = prop;
        }
    }

    public sealed class Property<TContainer, TValue> : PropertyBase
    {
        public Property(Expression<Func<TContainer, TValue>> accessor)
            : base(DependencyProperty.Register(accessor.MemberToString(), typeof(TValue), typeof(TContainer)))
        {
        }
        public Property(Expression<Func<TContainer, TValue>> accessor, PropertyMetadata metadata)
            : base(DependencyProperty.Register(accessor.MemberToString(), typeof(TValue), typeof(TContainer), metadata))
        {
        }
        public Property(Expression<Func<TContainer, TValue>> accessor, PropertyMetadata metadata, ValidateValueCallback callback)
            : base(DependencyProperty.Register(accessor.MemberToString(), typeof(TValue), typeof(TContainer), metadata, callback))
        {
        }
    }

    public sealed class AttachedProperty<TContainer, TValue> : PropertyBase
    {
        public AttachedProperty(Expression<Func<Property<TValue>>> accessor)
            : base(DependencyProperty.RegisterAttached(accessor.MemberToString().Substring(0,accessor.MemberToString().Length - "Property".Length), typeof(TValue), typeof(TContainer)))
        {
        }
        public AttachedProperty(Expression<Func<Property<TValue>>> accessor, PropertyMetadata metadata)
            : base(DependencyProperty.RegisterAttached(accessor.MemberToString().Substring(0, accessor.MemberToString().Length - "Property".Length), typeof(TValue), typeof(TContainer), metadata))
        {
        }
        public AttachedProperty(Expression<Func<Property<TValue>>> accessor, PropertyMetadata metadata, ValidateValueCallback callback)
            : base(DependencyProperty.RegisterAttached(accessor.MemberToString().Substring(0, accessor.MemberToString().Length - "Property".Length), typeof(TValue), typeof(TContainer), metadata, callback))
        {
        }
    }
}

The problem seems that it's connected to the fact that I'm using a class that is emulating a dependencyproperty (the property struct), while it's not directly a dependency property. 问题似乎与它连接到一个事实有关,即我使用的是模拟依赖项属性(属性struct)的类,而它不是直接依赖项属性。 Solved by using the normal dependency property 通过使用常规依赖项属性来解决

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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