Layers in XAML

Published 7/13/2013 by Christian
Tags: ,

This took me some time to figure out how to do. But as always, as soon as you figure it out, its actually quite simple.

I had two images I, in some cases, wanted to place on top of each other. It turns out, that if you put a given number objects into the same grid cell, they will be placed in layers.

<Grid>
	<Grid Grid.Column="0" Grid.Row="0"> 
		<Image Source="{Binding Path=Image}" />
	</Grid>
	<Grid Grid.Column="0" Grid.Row="0">
		<Image Source="{Binding Path=HoverImage}" />
	</Grid>
</Grid>

As always, feel free to comment, or ask.


OK this is not rocket science, but I keep forgetting.

To get the current mouse position relative to a control, System.Windows.Forms.Control has a static MousePosition property

System.Windows.Forms.Control.MousePosition

and a PointToClient method, which will take the screen coordinats as a Point as agument, and return a the client coordinates.

Eg. in a TreeView, this can be used to get the node the mouse is pointing at, as:

TreeNode editNode = treeView.GetNodeAt(treeView.PointToClient(System.Windows.Forms.Control.MousePosition));

As always, feel free to comment, or ask.


To ensure thread safety where Invoke is not implemented, can be done with a System.Windows.Threading.Dispatcher.

 

The Dispatcher should of course run on same thread as the thread safe instance, hence the Dispatcher instance should be created when the thread safe instance is constructed.

 

A little example is in order here, I guess.

Say that we have a object Foo accessed by object Bar, in Bar’ backgroundworker. This would cause a cross-thread exception

public class Foo
{
    private Object _fooBar;
    public Object FooBar
    {
        get { return _fooBar; }
        set { _fooBar = value; }
    }
    
    public Foo()
    {
    }
}

public class Bar
{
    private Foo _foo;
    public Foo Foo
    {
        get { return _foo; }
        set { _foo = value; }
    }
    
    public Bar()
    {
        this.Foo = new Foo();

        BackgroundWorker backgroundWorker = new BackgroundWorker();
        backgroundWorker.DoWork += backgroundWorker_DoWork;
    }

    void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        Foo.FooBar = NextFooBar();
    }

    private object NextFooBar()
    {
        return new Object();
    }
}

Since Foo don’t implement Invoke (or inherit from a object that does), one way to get about this would be to use a System.Windows.Threading.Dispatcher.

public class Foo
{
    private System.Windows.Threading.Dispatcher _dispatcher = null;
    private Object _fooBar;
    public Object FooBar
    {
        get { return _fooBar; }
        set { _dispatcher.Invoke(((Action<Object>))delegate(v) { internalSetFooBar(v); }, new object[] { value }); }
    }
    private void internalSetFooBar(object value)
    {
        _fooBar = value;
    }
    
    public Foo()
    {
        _dispatcher = System.Windows.Threading.Dispatcher.CurrentDispatcher;
    }
}

public class Bar
{
    private Foo _foo;
    public Foo Foo
    {
        get { return _foo; }
        set { _foo = value; }
    }
    
    public Bar()
    {
        this.Foo = new Foo();

        BackgroundWorker backgroundWorker = new BackgroundWorker();
        backgroundWorker.DoWork += backgroundWorker_DoWork;
    }

    void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        Foo.FooBar = NextFooBar();
    }

    private object NextFooBar()
    {
        return new Object();
    }
}

As always, feel free to comment, or ask.