WindowsFormsHost 和 DependencyProperty
我有一个 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
依赖属性的首要规则之一是除了
GetValue
和SetValue
调用之外,永远不要在 get 和 set 中包含任何逻辑。这是因为当它们在 XAML 中使用时,它们实际上并不通过 get 和 set 访问器。它们内联于GetValue
和SetValue
调用。所以你的代码都不会被执行。执行此操作的适当方法是使用
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
andSetValue
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 theGetValue
andSetValue
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 theDependencyProperty.Register
method. Then in the call-back you can then execute any extra code.