没有画布的Silverlight自定义鼠标光标作为root?

时间:2010-10-18 09:34:50

标签: silverlight-4.0

是否可以使用自定义鼠标指针(png图像),没有以Canvas作为根元素?使用Canvas作为root,鼠标可以工作(like here),但不幸的是我使用了几个自定义控件,这些控件在这样的设置中效果不佳:(

谢谢! 真知晶球

1 个答案:

答案 0 :(得分:3)

你无法摆脱使用画布,但这并不意味着你必须遵守画布如何安排事物。

我创建了一些对你有用的行为。

第一个是以下内容:

[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(例如Grid)的大小调整为父Canvas的大小。这意味着您可以在此FrameworkElement中创建自己的自定义布局,而无需担心Canvas处理排列的方式。

然后在您的XAML中,您可以执行以下操作:

<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

获取完整的工作代码

免责声明:严格来说,应该使用弱事件处理来实现此行为,以避免内存泄漏;但是这种实现超出了这个答案的范围。您可以在本网站上找到有关弱事件处理的更多信息,以及您是否需要它。