WindowsFormsHost 和 DependencyProperty

发布于 2024-08-29 21:28:03 字数 2736 浏览 4 评论 0原文

我有一个 Windows 窗体控件,我尝试使用 WindowsFormsHost 类将其包装为 WPF 控件;我想将遗留控件绑定到视图模型。具体来说,该控件公开了一个网格属性,GridVisible,我想将视图模型绑定到该属性。我使用私有静态支持字段和静态只读属性来表示依赖属性(功能上与静态公共字段相同,但不那么混乱)。当我尝试通过 XAML 设置控件的 GridVisible 属性时,它不会更新。有想法吗?我做错了什么?

DrawingHost 类

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

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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

笑着哭最痛 2024-09-05 21:28:03

依赖属性的首要规则之一是除了 GetValueSetValue 调用之外,永远不要在 get 和 set 中包含任何逻辑。这是因为当它们在 XAML 中使用时,它们实际上并不通过 get 和 set 访问器。它们内联于 GetValueSetValue 调用。所以你的代码都不会被执行。

执行此操作的适当方法是使用 DependencyProperty.Register 方法中的 PropertyMetadata 参数设置回调。然后在回调中您可以执行任何额外的代码。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文