为什么我不能绑定到这个依赖属性?

时间:2011-11-27 14:22:53

标签: c# wpf xaml binding

我不明白为什么我无法将自定义宽度依赖项属性(我的自定义控件)绑定到另一个自定义控件依赖项属性。

我遵循了所有指导方针我非常确定依赖属性已得到很好的实施。

Window(BlackAndWhiteWindow),Canvas(所有这些都是自定义控件,而不是来自wpf的控件)都继承自控件。

有什么建议吗?我疯了......

Visual Studio错误声明无法绑定属性,因为您只能将依赖项属性绑定到依赖项对象,但它们是依赖项对象,并且我绑定到依赖项属性!!

编辑1:

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>

控制类

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
    }
}

画布类

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

窗口类

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

物业类

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))
        {
        }
    }
}

1 个答案:

答案 0 :(得分:1)

问题似乎与我正在使用一个模拟依赖项属性(属性结构)的类有关,而它不是直接依赖属性。通过使用正常依赖属性

解决