views:

190

answers:

1

I've got a Windows Forms control that I'm attempting to wrap as a WPF control using the WindowsFormsHost class; I would like to bind the legacy control to a view-model. Specifically, the control exposes a grid property, GridVisible, that I would like to bind a view-model to. I'm using a private, static backing field and a static, read-only property to represent the dependency property (functionally the same as a static, public field, but less mess). When I attempt to set the control's GridVisible property via XAML, it's not updating. Ideas? What am I doing incorrectly?

DrawingHost Class

/// <summary>
/// Provides encapsulation of a drawing control.
/// </summary>
public class DrawingHost : WindowsFormsHost
{
    #region Data Members

    /// <summary>
    /// Holds the disposal flag.
    /// </summary>
    private bool disposed;

    /// <summary>
    /// Holds the grid visible property.
    /// </summary>
    private static readonly DependencyProperty gridVisibleProperty =
        DependencyProperty.Register("GridVisible", typeof(bool),
        typeof(DrawingHost), new FrameworkPropertyMetadata(false,
            FrameworkPropertyMetadataOptions.AffectsRender |
            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

    /// <summary>
    /// Holds the pad.
    /// </summary>
    private readonly DrawingPad pad = new DrawingPad();

    #endregion

    #region Properties

    /// <summary>
    /// Get or set whether the grid is visible.
    /// </summary>
    public bool GridVisible
    {
        get { return (bool)GetValue(GridVisibleProperty); }
        set { SetValue(GridVisibleProperty, pad.GridVisible = value); }
    }

    /// <summary>
    /// Get the grid visible property.
    /// </summary>
    public static DependencyProperty GridVisibleProperty
    {
        get { return gridVisibleProperty; }
    }

    #endregion

    /// <summary>
    /// Default-construct a drawing host.
    /// </summary>
    public DrawingHost()
    {
        this.Child = this.pad;
    }

    /// <summary>
    /// Dispose of the drawing host.
    /// </summary>
    /// <param name="disposing">The disposal invocation flag.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && !disposed)
        {
            if (pad != null)
            {
                pad.Dispose();
            }
            disposed = true;
        }
        base.Dispose(disposing);
    }
}


XAML

<UserControl x:Class="Drawing.DrawingView"
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" 
mc:Ignorable="d" 
xmlns:local="clr-namespace:Drawing">
<local:DrawingHost GridVisible="True"/></UserControl>
A: 

One of the first rules of dependency properties is to never include any logic in the get and set except the GetValue and SetValue calls. This is because when they are used in XAML, they do not actually go through the get and set accessors. They are inlined with the GetValue and SetValue calls. So none of your code will be executed.

The appropriate way to do this is set up a call-back using the PropertyMetadata parameter in the DependencyProperty.Register method. Then in the call-back you can then execute any extra code.

Charlie
Thanks, Charlie! I specified an assignment callback and it works as expected.
Chris