你不能逃避使用画布,但这并不意味着你必须遵守画布如何安排事情。
我创造了一些对你有用的行为。
第一种是:
[TypeConstraint(typeof(Canvas))]
public class MouseCursorAction : TargetedTriggerAction<UIElement>
{
protected override void Invoke(object parameter)
{
}
protected override void OnAttached()
{
var canvas = AssociatedObject as Canvas;
if (canvas == null) { return; }
canvas.MouseMove += new MouseEventHandler(canvas_MouseMove);
canvas.MouseEnter += new MouseEventHandler(canvas_MouseEnter);
canvas.MouseLeave += new MouseEventHandler(canvas_MouseLeave);
}
void canvas_MouseLeave(object sender, MouseEventArgs e)
{
Target.Visibility = Visibility.Collapsed;
}
void canvas_MouseEnter(object sender, MouseEventArgs e)
{
Target.Visibility = Visibility.Visible;
}
void canvas_MouseMove(object sender, MouseEventArgs e)
{
var canvas = sender as Canvas;
var positionInCanvas = e.GetPosition(canvas);
Canvas.SetTop(Target, positionInCanvas.Y);
Canvas.SetLeft(Target, positionInCanvas.X);
}
}
通过这种行为,您可以转换鼠标光标中的任何UIElement。只需将其设置为画布并选择鼠标光标所需的目标。
现在,为了解决布局问题,我创建了另一个行为:
[TypeConstraint(typeof(Canvas))]
public class FillCanvasAction : TargetedTriggerAction<FrameworkElement>
{
protected override void Invoke(object parameter)
{
}
protected override void OnAttached()
{
var canvas = AssociatedObject as Canvas;
if (canvas == null) { return; }
canvas.SizeChanged += new SizeChangedEventHandler(Target_SizeChanged);
}
void Target_SizeChanged(object sender, SizeChangedEventArgs e)
{
var element = Target;
if (element == null) { return; }
var canvas = sender as Canvas;
element.Width = canvas.ActualWidth;
element.Height = canvas.ActualHeight;
Canvas.SetTop(element, 0);
Canvas.SetLeft(element, 0);
}
}
当附加到父画布时,此行为会将目标FrameworkElement(例如网格)的大小调整为父画布的大小。这意味着您可以在这个FrameworkElement中创建自己的自定义布局,而不必担心Canvas处理布局的方式。
<Grid x:Name="LayoutRoot" Cursor="None">
<Canvas x:Name="canvas" Background="Black">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<local:MouseCursorAction TargetObject="{Binding ElementName=cursorImage}"/>
</i:EventTrigger>
<i:EventTrigger>
<local:FillCanvasAction TargetObject="{Binding ElementName=grid}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<Grid x:Name="grid" Background="White" Width="600" Height="400">
<!-- Create your layout here -->
</Grid>
<Image x:Name="cursorImage" Height="50" Width="50" Source="mouse_cursor.png"/>
</Canvas>
</Grid>
你可以从
here
免责声明:严格来说,应该使用弱事件处理来实现此行为,以避免内存泄漏;但是,该实现超出了此答案的范围。你可以在这个网站上找到更多关于弱事件处理的信息,以及你的项目是否需要它。