非WPF实例回调到WPF-Control派生类。更改DependencyProperty

时间:2011-07-18 10:21:22

标签: wpf callback wpf-controls dependency-properties

  1. WPF控件派生类的组合为非WPF控件派生类。后一类,比如 Inner ,应该触发外部类WPF DependencyProperty更改。

  2. 基本不变量是我的内部类不应强制使用任何WPF名称空间,其中 Inner 是API的一部分我正在创建一个DLL。因此,从任何WPF类继承都不是合适的解决方案。

  3. 实现从非.NET派生类到WPF-Control类的回调以更改DependencyProperty对象的最佳(或至少是任意)方法。

    发现了一些假设的回调机制:

    • c#delegates和c#events

    无法解决这个问题,因为它会引发运行时异常

    The calling thread cannot access this object because a different thread owns it.
    

    当回调机制试图修改Background属性时(我认为是DependancyProperty对象的关键,或者至少是.NET定义的属性)。

    我猜c#delegates不能以单线程方式工作 - 但是,我在阅读c#文档时没有发现这个事实。

    (一种解决方案是通过.NET Dispatcher类和Invoke(),但它似乎太随意而且可能很慢 - 不再是WPF友好的方式吗?)

    • 我读过路由事件和DependencyProperties

    在WPF文档中(但是还没有对此进行测试),但似乎Routed事件无法帮助(因为我的 Inner 类不是VisualTree的一部分)而且我不应该继承的DependencyObject。

    我读了(我想)与我的问题相关的一切。如果有人提出类似的问题,我很抱歉,如果你引导我到那个话题,我很高兴,如果问题的本质是相同的。

    简化示例:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Controls;
    using System.Windows.Media;
    using System.Timers;
    
    namespace WpfApplication4
    {
        internal class Rect:ContentControl
        {
            Inner inner = new Inner();
    
            public Rect()
            {
                inner.Rotate += new Inner.RotateEventHandler(rotated);
            }
    
            public void rotated(object sender, RotateEventArgs args)
            {
                Background = Brushes.Blue;                            //Run time error
                VisualTransform = new RotateTransform(args.Angle);  //Run time error
            }
        }
    
        public class Inner
        {
            Timer timer = new Timer(200);
    
            public Inner()
            {
                timer.Enabled = true;
                timer.Elapsed +=new ElapsedEventHandler(elapsed);
            }
    
            public delegate void RotateEventHandler(object sender, RotateEventArgs args);
            public event RotateEventHandler Rotate;
    
            public void elapsed(object sender, ElapsedEventArgs e)
            {
                RotateEventArgs args = new RotateEventArgs();
                args.Angle = args.Angle + 45;
                OnRotate(args);
            }
    
            protected void OnRotate(RotateEventArgs e)
            {
                if (e != null)
                {
                    Rotate(this, e);
                }
            }
        }
    
        internal class RotateEventArgs
        {
            private double angle = 0;
    
            public double Angle
            {
                set { angle = value; }
                get { return angle; }
            }
        }
    }
    

1 个答案:

答案 0 :(得分:0)

您可以使用DispatchTimer代替Timer。在DispatchTimer类中拥有Rect