我怎样才能突出线时,用户在WPF悬停? [英] How can i highlight line when user hovers over it in wpf?

查看:178
本文介绍了我怎样才能突出线时,用户在WPF悬停?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前用户可以通过单击并拖动鼠标它们在画布上绘制。我怎样才能改变线条的颜色来表示用户的光标悬停在该行?这将是理想的,使当光标在任何给定的行5个像素来表示他们关闭它凸显。



Inital图纸...





:当用户的光标无论是徘徊在直接或在任何给定的行5个像素。





MainWindow.xaml

 <窗​​口x:类= WpfApplication1.MainWindow
的xmlns =http://schemas.microsoft.com/winfx/2006/xaml/presentation
的xmlns:X =http://schemas.microsoft.com/winfx/ 2006 / XAML
的xmlns:D =http://schemas.microsoft.com/expression/blend/2008
的xmlns:MC =http://schemas.openxmlformats.org/markup-兼容性/ 2006年的
的xmlns:地方=CLR的命名空间:WpfApplication1
MC:可忽略=D
标题=主窗口HEIGHT =350WIDTH =525> ;
<网格和GT;
<帆布NAME =paintSurface的MouseDown =Canvas_MouseDown_1的MouseMove =Canvas_MouseMove_1>
< Canvas.Background>
<的SolidColorBrush颜色=白不透明度=0/>
< /Canvas.Background>
< /帆布>
< /网格和GT;
< /窗GT;



MainWindow.cs



 使用System.Windows; 
使用System.Windows.Input;使用System.Windows.Shapes
;

命名空间WpfApplication1
{
///<总结> $ B $为MainWindow.xaml
///< b ///交互逻辑; /总结>
公共部分类主窗口:窗口
{
点currentPoint =新点();

公共主窗口()
{
的InitializeComponent();
}

私人无效Canvas_MouseDown_1(对象发件人,System.Windows.Input.MouseButtonEventArgs E)
{
如果(e.ButtonState == MouseButtonState.Pressed)
currentPoint = e.GetPosition(本);
}

私人无效Canvas_MouseMove_1(对象发件人,System.Windows.Input.MouseEventArgs E)
{
如果(e.LeftButton == MouseButtonState.Pressed)
{
线线=新线();

line.Stroke = SystemColors.WindowFrameBrush;
line.X1 = currentPoint.X;
line.Y1 = currentPoint.Y;
line.X2 = e.GetPosition(本).X;
line.Y2 = e.GetPosition(本).Y;

currentPoint = e.GetPosition(本);

paintSurface.Children.Add(线);
}
}

}
}


解决方案

注意:有示例程序的两个版本在这里,新老。看看这两个让你可以做什么的想法。




下面是修复你是不知道问题的示例应用程序,这是你画的许多线,一举而不是单行线的事实。您应该使用折线。如果您使用Visual Studio 2015年,然后有一个Live可视化树,它会告诉你正是我的意思;否则,你可以使用一个工具,如史努比看到同样的事情。它还涉及您原来的问题,这是突出。



新版本是这里示出的第一代码部分。它使用一本字典链接基线和突出的线条,这样你就可以得到下面的底线,如果需要(当你想删除它,如)。这也凸显了基地,相对于突出亮点线,这是老版做了什么。高亮线只是用于选择区缓冲区。 。增加或减少其行程,以获得所需的选择缓冲区(你在帖子中提到5个像素)



预览:





XAML:

 <窗​​口x:类=WpfApplication.MainWindow
的xmlns =htt​​p://schemas.microsoft.com/winfx/ 2006 / XAML /演示
的xmlns:X =http://schemas.microsoft.com/winfx/2006/xaml
的xmlns:D =http://schemas.microsoft.com/表达/混合/ 2008
的xmlns:MC =http://schemas.openxmlformats.org/markup-compatibility/2006
的xmlns:地方=CLR的命名空间:WpfApplication
MC:可忽略=D
标题=主窗口HEIGHT =350WIDTH =525>
<帆布NAME =paintSurface背景=白的MouseDown =Canvas_MouseDown
的MouseUp =Canvas_MouseUp的MouseMove =Canvas_MouseMove/>
< /窗GT;



C#:



 使用System.Collections.Generic;使用System.Windows 
;
使用System.Windows.Input;使用System.Windows.Media
;使用System.Windows.Shapes
;

命名空间WpfApplication
{
公共部分类主窗口:窗口
{
折线_baseLine;
折线_highlightLine;
点_currentPoint;
布尔_newLine;

&字典LT;折线,折线> _lines =新词典<折线,折线>();

公共主窗口()
{
的InitializeComponent();
}

私人无效Canvas_MouseDown(对象发件人,MouseButtonEventArgs E)
{
_newLine = TRUE;
}

私人无效Canvas_MouseUp(对象发件人,MouseButtonEventArgs E)
{
如果(_highlightLine = NULL&放大器;!&安培;!_newline)
{
_highlightLine.MouseEnter + = ShowHighlight;
_highlightLine.MouseLeave + = HideHighlight;
}
}

私人无效Canvas_MouseMove(对象发件人,MouseEventArgs E)
{
如果(e.LeftButton == MouseButtonState.Pressed)
{
如果(_newLine)
{
_baseLine =新的折线
{
行程= SystemColors.WindowFrameBrush,
StrokeThickness = 1.0
};
_highlightLine =新的折线
{
=透明度0.0,
行程= SystemColors.WindowFrameBrush,
StrokeThickness = 10.0
};

paintSurface.Children.Add(_baseLine);
paintSurface.Children.Add(_highlightLine);
_lines.Add(_highlightLine,_baseLine);
_newLine = FALSE;
}

_currentPoint = e.GetPosition(本);
_baseLine.Points.Add(_currentPoint);
_highlightLine.Points.Add(_currentPoint);
}
}

私人无效ShowHighlight(对象发件人,MouseEventArgs E)
{
无功行=发件人为折线;
如果(行!= NULL)
{
_lines [行] .Stroke =新的SolidColorBrush(Colors.LimeGreen);
}
}

私人无效HideHighlight(对象发件人,MouseEventArgs E)
{
无功行=发件人为折线;
如果(行!= NULL)
{
_lines [行] .Stroke = SystemColors.WindowFrameBrush;
}
}
}
}

您会注意到的_newLine旗布尔。我用它来指示新的折线是否应绘制。当鼠标下来,这是一个新行需要创建一个指标。我不勾起来的MouseEnter和鼠标离开处理为线,直至鼠标,因为我不想强调要在该行的绘制过程分心。你必须给一些中风的_highlightLine,然后设置其不透明度为0,使其不可见,但仍应对打击试验;否则,的MouseEnter和鼠标离开处理程序将永远不会被调用。



OLD(老版本的程序仍然是一个不错的退房。):



我在这里做的是关于基地之一的顶部添加高亮折线,并设置其行程为10,而不是基地的1你可以调整行程厚度让自己所需的选择缓冲地带。我真的对这个花了大约10至15分钟,这样有可能会对其进行改进的方式,但是这应该给你一个坚实的基础,建立在。如果你希望在你突出这些行执行某些动作的道路,这样能够删除它们,那么我建议增加两个_baseLine和_highlightLine到词典,其中_highlightLine是关键,_baseLine是值。这样,当您选择_highlightLine,您可以访问底层_baseLine



预览:





XAML:

 <窗​​口x:类=WpfApplication.MainWindow
的xmlns =htt​​p://schemas.microsoft.com/winfx/2006/xaml/presentation
的xmlns:X =http://schemas.microsoft.com/winfx/2006/xaml
的xmlns:D =http://schemas.microsoft.com/expression/blend/2008
的xmlns:MC =http://schemas.openxmlformats.org/markup-compatibility/2006
的xmlns:地方=CLR的命名空间:WpfApplication
MC:可忽略= D
标题=主窗口HEIGHT =350WIDTH =525>
<帆布NAME =paintSurface背景=白的MouseDown =Canvas_MouseDown
的MouseUp =Canvas_MouseUp的MouseMove =Canvas_MouseMove/>
< /窗GT;



C#:



 使用System.Windows; 
使用System.Windows.Input;使用System.Windows.Media
;使用System.Windows.Shapes
;

命名空间WpfApplication
{
公共部分类主窗口:窗口
{
折线_baseLine;
折线_highlightLine;
点_currentPoint;
布尔_newLine;

公共主窗口()
{
的InitializeComponent();
}

私人无效Canvas_MouseDown(对象发件人,MouseButtonEventArgs E)
{
_newLine = TRUE;
}

私人无效Canvas_MouseUp(对象发件人,MouseButtonEventArgs E)
{
如果(_highlightLine = NULL&放大器;!&安培;!_newline)
{
_highlightLine.MouseEnter + = ShowHighlight;
_highlightLine.MouseLeave + = HideHighlight;
}
}

私人无效Canvas_MouseMove(对象发件人,MouseEventArgs E)
{
如果(e.LeftButton == MouseButtonState.Pressed)
{
如果(_newLine)
{
_baseLine =新的折线
{
行程= SystemColors.WindowFrameBrush,
StrokeThickness = 1.0
};
_highlightLine =新的折线
{
行程=新的SolidColorBrush(Colors.Green),
=透明度0.0,
StrokeThickness = 10.0
};

paintSurface.Children.Add(_baseLine);
paintSurface.Children.Add(_highlightLine);
_newLine = FALSE;
}

_currentPoint = e.GetPosition(本);
_baseLine.Points.Add(_currentPoint);
_highlightLine.Points.Add(_currentPoint);
}
}

私人无效ShowHighlight(对象发件人,MouseEventArgs E)
{
无功行=发件人为折线;
如果(行!= NULL)
{
line.Opacity = 1.0;
}
}

私人无效HideHighlight(对象发件人,MouseEventArgs E)
{
无功行=发件人为折线;
如果(行!= NULL)
{
line.Opacity = 0.0;
}
}
}
}

其他的思考:



如果你想尽可能走的造型充分的XAML,你有几种选择。第一种选择是创建一个样式,突出TargetType的折线在IsMouseOver属性为真;但是,您将不能获得这一个5像素缓冲区。为了实现这个目标5像素缓冲区,你需要创建一个自定义模板,它需要比我在这里表现出更多的工作。当然...如果你感觉很冒险,总是有从外形派生并自己创建的highlightable /可选择折线的选择 - 它只是一个大量的工作,比起上面的代码。光明的一面是,这将是可重复使用的。这只是取决于你的情况,需求和欲望。


Currently users can draw on the canvas by clicking and dragging their mouse. How can I change the color of the line to indicate the user's cursor is hovering over the line? It would be ideal to make it highlight when the cursor is within 5 pixels of any given line to indicate they are close.

Inital drawing...

When user's cursor is either hovering directly over or within 5 pixels of any given line.

MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Canvas  Name="paintSurface" MouseDown="Canvas_MouseDown_1" MouseMove="Canvas_MouseMove_1" >
            <Canvas.Background>
                <SolidColorBrush Color="White" Opacity="0"/>
            </Canvas.Background>
        </Canvas>
    </Grid>
</Window>

MainWindow.cs

using System.Windows;
using System.Windows.Input;
using System.Windows.Shapes;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        Point currentPoint = new Point();

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Canvas_MouseDown_1(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (e.ButtonState == MouseButtonState.Pressed)
                currentPoint = e.GetPosition(this);
        }

        private void Canvas_MouseMove_1(object sender, System.Windows.Input.MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                Line line = new Line();

                line.Stroke = SystemColors.WindowFrameBrush;
                line.X1 = currentPoint.X;
                line.Y1 = currentPoint.Y;
                line.X2 = e.GetPosition(this).X;
                line.Y2 = e.GetPosition(this).Y;

                currentPoint = e.GetPosition(this);

                paintSurface.Children.Add(line);
            }
        }

    }
}

解决方案

Note: There are two versions of the sample program here, new and old. Take a look at both to get an idea of what you can do.

Here's a sample application that fixes the issue you were unaware of, which is the fact that you drew numerous lines with one stroke and not a single line. You should use a Polyline. If you use Visual Studio 2015, then there's a Live Visual Tree, which will show you exactly what I mean; otherwise, you can use a tool such as Snoop to see the same thing. It also addresses you original question, which is the highlighting.

The new version is the first code portion that is shown here. It uses a dictionary to link base line and highlight lines, so that you may get to the underlying base line if need to (such as when you want to delete it). It also highlights the base, versus the highlighting the highlight line, which is what the old version did. The highlight line is simply used for the selection zone buffer. Increase or decrease its stroke to get the desired selection buffer (you mentioned 5 pixels in your post).

Preview:

XAML:

<Window x:Class="WpfApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Canvas Name="paintSurface" Background="White" MouseDown="Canvas_MouseDown" 
            MouseUp="Canvas_MouseUp" MouseMove="Canvas_MouseMove"/>
</Window>

C#:

using System.Collections.Generic;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;

namespace WpfApplication
{
    public partial class MainWindow : Window
    {
        Polyline _baseLine;
        Polyline _highlightLine;
        Point _currentPoint;
        bool _newLine;

        Dictionary<Polyline, Polyline> _lines = new Dictionary<Polyline, Polyline>();

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
        {
            _newLine = true;
        }

        private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (_highlightLine != null  && !_newline)
            {
                _highlightLine.MouseEnter += ShowHighlight;
                _highlightLine.MouseLeave += HideHighlight;
            }
        }

        private void Canvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                if (_newLine)
                {
                    _baseLine = new Polyline
                    {
                        Stroke = SystemColors.WindowFrameBrush,
                        StrokeThickness = 1.0
                    };
                    _highlightLine = new Polyline
                    {
                        Opacity = 0.0,
                        Stroke = SystemColors.WindowFrameBrush,
                        StrokeThickness = 10.0
                    };

                    paintSurface.Children.Add(_baseLine);
                    paintSurface.Children.Add(_highlightLine);
                    _lines.Add(_highlightLine, _baseLine);
                    _newLine = false;
                }

                _currentPoint = e.GetPosition(this);
                _baseLine.Points.Add(_currentPoint);
                _highlightLine.Points.Add(_currentPoint);
            }
        }

        private void ShowHighlight(object sender, MouseEventArgs e)
        {
            var line = sender as Polyline;
            if (line != null)
            {
                _lines[line].Stroke = new SolidColorBrush(Colors.LimeGreen);
            }
        }

        private void HideHighlight(object sender, MouseEventArgs e)
        {
            var line = sender as Polyline;
            if (line != null)
            {
                _lines[line].Stroke = SystemColors.WindowFrameBrush;
            }
        }
    }
}

You'll notice the _newLine flag boolean. I use it to indicate whether a new Polyline should be drawn. When the mouse is down, that's an indicator that a new line needs to be created. I don't hook up the MouseEnter and MouseLeave handles for the line until the mouse is up because I don't want highlighting to be distracting during the drawing process of the line. You have to give some sort of stroke to the _highlightLine and then set its opacity to 0 to make it invisible, but still respond to hit tests; otherwise, MouseEnter and MouseLeave handlers will never get invoked.

OLD (The old version of the program. Still a good one to check out.):

What I do here is add a highlighting polyline on top of the base one and set its stroke to be 10 instead of the base's 1. You can adjust that stroke thickness to get yourself the desired selection "buffer" zone. I literally spent about 10-15 minutes on this, so there could be ways to improve it, but this should give you a solid base to build upon. If you wish to perform some actions down the road on these lines you're highlighting, such being able to delete them, then I suggest adding both the _baseLine and the _highlightLine to a dictionary, where _highlightLine is the key and _baseLine is the value. That way, when you select the _highlightLine, you may access the underlying _baseLine.

Preview:

XAML:

<Window x:Class="WpfApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Canvas Name="paintSurface" Background="White" MouseDown="Canvas_MouseDown" 
            MouseUp="Canvas_MouseUp" MouseMove="Canvas_MouseMove"/>
</Window>

C#:

using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;

namespace WpfApplication
{
    public partial class MainWindow : Window
    {
        Polyline _baseLine;
        Polyline _highlightLine;
        Point _currentPoint;
        bool _newLine;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
        {
            _newLine = true;
        }

        private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (_highlightLine != null && !_newline)
            {
                _highlightLine.MouseEnter += ShowHighlight;
                _highlightLine.MouseLeave += HideHighlight;
            }
        }

        private void Canvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                if (_newLine)
                {
                    _baseLine = new Polyline
                    {
                        Stroke = SystemColors.WindowFrameBrush,
                        StrokeThickness = 1.0
                    };
                    _highlightLine = new Polyline
                    {
                        Stroke = new SolidColorBrush(Colors.Green),
                        Opacity = 0.0,
                        StrokeThickness = 10.0
                    };

                    paintSurface.Children.Add(_baseLine);
                    paintSurface.Children.Add(_highlightLine);
                    _newLine = false;
                }

                _currentPoint = e.GetPosition(this);
                _baseLine.Points.Add(_currentPoint);
                _highlightLine.Points.Add(_currentPoint);
            }
        }

        private void ShowHighlight(object sender, MouseEventArgs e)
        {
            var line = sender as Polyline;
            if (line != null)
            {
                line.Opacity = 1.0;
            }
        }

        private void HideHighlight(object sender, MouseEventArgs e)
        {
            var line = sender as Polyline;
            if (line != null)
            {
                line.Opacity = 0.0;
            }
        }
    }
}

Additional Thoughts:

If you want to go full XAML as far as styling, you've got a few options. First option is to create a style that highlights TargetType Polyline on IsMouseOver property being true; however, you won't get the 5 pixel buffer with this one. To accomplish that 5 pixel buffer, you'd need to create a custom template, which requires more work than what I've demonstrated here. Of course... if you're feeling very adventurous, there's always the option of deriving from Shape and create yourself a highlightable/selectable Polyline -- it's just a lot of work, compared to the above code. The bright side is that it'll be reusable. It just depends on your situation, needs and wants.

这篇关于我怎样才能突出线时,用户在WPF悬停?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆