基于FrameworkElement在自定义控件上实现鼠标交互
Implement mouse interaction on custom control based on FrameworkElement
这只是学习的例子。
我想创建外观完全不同的自定义控件。因此,根据 https://docs.microsoft.com/en-us/dotnet/framework/wpf/controls/control-authoring-overview,我从 FrameworkElement
并覆盖 OnRender
方法,如果需要,也可以覆盖 OverriderMesure
和 ArrangeOverride
。
现在我想实现鼠标交互,例如:悬停时颜色从红色变为蓝色。我应该怎么做?
public class Box : FrameworkElement
{
private static Color defaultColor = Colors.Red;
public static DependencyProperty ColorProperty = DependencyProperty.Register("Color", typeof(SolidColorBrush), typeof(Box),
new FrameworkPropertyMetadata(new SolidColorBrush(defaultColor), FrameworkPropertyMetadataOptions.AffectsRender));
public SolidColorBrush Color
{
get { return (SolidColorBrush)GetValue(ColorProperty); }
set { SetValue(ColorProperty, value); }
}
static Box()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(Box), new FrameworkPropertyMetadata(typeof(Box)));
}
protected override void OnRender(DrawingContext drawingContext)
{
// It's just example, I know shape is wayyy too simple to involve custom render.
drawingContext.DrawRectangle(Color, null, new Rect(0, 0, ActualWidth, ActualWidth));
}
protected override void OnMouseEnter(MouseEventArgs e)
{
Color = new SolidColorBrush(Colors.Blue); // Set to color
}
protected override void OnMouseLeave(MouseEventArgs e)
{
Color = new SolidColorBrush(defaultColor); // Back to default
}
protected override Size MeasureOverride(Size constraint)
{
...
}
protected override Size ArrangeOverride(Size finalSize)
{
...
}
}
到目前为止我推断:
通常,如果我从 Control
派生,我会为此使用 VSM。不幸的是,VSM 在 ControlTemplate
层级树之前不可用,因此控件具有 Template
属性。因此,如果我决定自己绘制控件,我需要使用此路由事件,在此特定示例中 OnMouseEnter(MouseEventArgs)
、OnMouseLeave(MouseEventArgs)
和一些依赖项 属性,如上面的代码。
这是正确的做法吗?请记住这是为了学习目的,所以 FrameworkElement
作为基础是必须的。
我可以看到一些缺点,因为如果我们想要控制悬停颜色(在上面的代码中被硬编码为蓝色)我需要处理后面的代码,或者为此创建另一个依赖项 属性。
Unfortunately VSM isn't available until ControlTemplate hierarchy tree, so controls which have Template property.
这不是真的。
您可以正常使用VSM,稍作改动。阅读:https://msdn.microsoft.com/en-us/library/system.windows.visualstatemanager(v=vs.110).aspx#Examples。仔细看看例子。
这只是学习的例子。
我想创建外观完全不同的自定义控件。因此,根据 https://docs.microsoft.com/en-us/dotnet/framework/wpf/controls/control-authoring-overview,我从 FrameworkElement
并覆盖 OnRender
方法,如果需要,也可以覆盖 OverriderMesure
和 ArrangeOverride
。
现在我想实现鼠标交互,例如:悬停时颜色从红色变为蓝色。我应该怎么做?
public class Box : FrameworkElement
{
private static Color defaultColor = Colors.Red;
public static DependencyProperty ColorProperty = DependencyProperty.Register("Color", typeof(SolidColorBrush), typeof(Box),
new FrameworkPropertyMetadata(new SolidColorBrush(defaultColor), FrameworkPropertyMetadataOptions.AffectsRender));
public SolidColorBrush Color
{
get { return (SolidColorBrush)GetValue(ColorProperty); }
set { SetValue(ColorProperty, value); }
}
static Box()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(Box), new FrameworkPropertyMetadata(typeof(Box)));
}
protected override void OnRender(DrawingContext drawingContext)
{
// It's just example, I know shape is wayyy too simple to involve custom render.
drawingContext.DrawRectangle(Color, null, new Rect(0, 0, ActualWidth, ActualWidth));
}
protected override void OnMouseEnter(MouseEventArgs e)
{
Color = new SolidColorBrush(Colors.Blue); // Set to color
}
protected override void OnMouseLeave(MouseEventArgs e)
{
Color = new SolidColorBrush(defaultColor); // Back to default
}
protected override Size MeasureOverride(Size constraint)
{
...
}
protected override Size ArrangeOverride(Size finalSize)
{
...
}
}
到目前为止我推断:
通常,如果我从 Control
派生,我会为此使用 VSM。不幸的是,VSM 在 ControlTemplate
层级树之前不可用,因此控件具有 Template
属性。因此,如果我决定自己绘制控件,我需要使用此路由事件,在此特定示例中 OnMouseEnter(MouseEventArgs)
、OnMouseLeave(MouseEventArgs)
和一些依赖项 属性,如上面的代码。
这是正确的做法吗?请记住这是为了学习目的,所以 FrameworkElement
作为基础是必须的。
我可以看到一些缺点,因为如果我们想要控制悬停颜色(在上面的代码中被硬编码为蓝色)我需要处理后面的代码,或者为此创建另一个依赖项 属性。
Unfortunately VSM isn't available until ControlTemplate hierarchy tree, so controls which have Template property.
这不是真的。
您可以正常使用VSM,稍作改动。阅读:https://msdn.microsoft.com/en-us/library/system.windows.visualstatemanager(v=vs.110).aspx#Examples。仔细看看例子。