-
WPF control-derived class has a composition of non-WPF control-derived class. The latter class, say Inner, should trigger an Outer class WPF DependencyProperty change.
-
Essential invariant is that my Inner class shouldn’t force any WPF namespaces to use whereby, Inner is part of API of a dll I am creating. So Inheritance from any WPF class is not appropriate solution.
What could be the best (or at least arbitraty) way to implement a callback from non-.NET derived class to a WPF-Control class to change a DependencyProperty object.
Some hypothetical callback mechanisms found:
- c# delegates and c# events.
Can’t solve this, becouce it is thrown a runtime exception
The calling thread cannot access this object because a different thread owns it.
when a callback mechanism tries to modify Background property (a DependancyProperty object I think is the key, or at least .NET defined property).
I guess that c# delegates doesn’t work in single-threading manner – however, i didn’t find this fact while reading c# documentation.
(One solution is through .NET Dispatcher class and Invoke(), but it seems too arbitrary and possibly slow – isn’t any more WPF-friendly way?)
- I had read about Routed events and DependencyProperties
in WPF documentation (however had’t tested this yet), but it seems Routed event cant help (because my Inner class isn’t part of a VisualTree) and I should’t inherit from DependencyObject.
I read (I suppose) everything relevant to my problem. I’m sorry if some similar kind of question had been asked, I would be glad if you direct me to that thread, if the problem essence is the same.
Simplified example:
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; }
}
}
}
You can make use of
DispatchTimerinstead ofTimer. Have theDispatchTimerin theRectclass itself.