我正在尝试按下鼠标进入按钮时内容发生变化的按钮。 目前,这是我正在使用的代码:
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<Button x:Name="One"
Content="ONE"
Height="50"
Width="Auto"
MouseEnter="One_OnMouseEnter"
MouseLeave="One_OnMouseLeave" />
<Button x:Name="Two"
PreviewMouseMove="Two_OnMouseEnter">
<Grid>
<Ellipse Fill="Black"
Height="40"
Width="40" />
<Label Content="TWO"
Foreground="White"
VerticalAlignment="Center"
HorizontalAlignment="Center" />
</Grid>
</Button>
</StackPanel>
</StackPanel>
private void One_OnMouseEnter(object sender, MouseEventArgs e)
{
Button b = sender as Button;
if (b != null)
{
b.Foreground = Brushes.Purple;
b.FontSize = 24;
}
}
private void One_OnMouseLeave(object sender, MouseEventArgs e)
{
Button b = sender as Button;
if (b != null)
{
b.Foreground = Brushes.Black;
b.FontSize = 12;
}
}
private void Two_OnMouseEnter(object sender, MouseEventArgs e)
{
Ellipse el = sender as Ellipse;
if (el != null)
{
el.Height = 60;
el.Width = 60;
el.Fill = Brushes.White;
}
Label l = sender as Label;
if (l != null)
{
l.Foreground = Brushes.Black;
}
Grid g = sender as Grid;
if (g != null)
{
g.Height = 200;
g.Width = 200;
}
}
第一个按钮按预期工作。 当鼠标移动到“一个”按钮时,文本内容会按预期更改。文本颜色变为紫色,字体大小增加。
我正在尝试用第二个按钮做类似的事情。增加尺寸并更改椭圆的颜色,更改标签的颜色,并更改网格的大小。
问题是第二个按钮似乎没有按预期响应。我尝试使用PreviewMouseMove
,我理解使用隧道路由策略,它应该触发Button的子元素。我使用了断点来检查,事件似乎只是在发送者是Button的情况下触发。
我的问题是:为什么不会对孩子们提出这个事件,因为我已经知道隧道路由策略应该有效,我该怎么做才能解决它?
此外,MouseEnter和MouseLeave事件似乎遵循冒泡路由策略,但行为更类似于我想要做的事情。我可以强制使用隧道路由策略吗?
为了进一步解释这个项目的目标:
我打算做的是更全面地了解WPF中的事件隧道。
今天早上,我更多地检查了这本书,并找到了一种方法,当鼠标进入每个特定孩子的区域时,这是一项改进。
以下是C#Code-Behind文件中的新代码:
private void Two_OnMouseEnter(object sender, MouseEventArgs e)
{
Ellipse el = e.OriginalSource as Ellipse;
if (el != null)
{
el.Height = 60;
el.Width = 60;
el.Fill = Brushes.Orange;
}
TextBlock t = e.OriginalSource as TextBlock;
if (t != null)
{
t.Foreground = Brushes.Blue;
}
Grid g = e.OriginalSource as Grid;
if (g != null)
{
g.Height = 200;
g.Width = 200;
}
}
与此代码的不同之处在于它使用方法签名中的MouseEventArgs e
对象,将e.OriginalSource
作为对象类型而不是转换sender
对象。
此外,使用XAML文件中的PreviewMouseMove
事件调用调用此代码:
<Button x:Name="Two" PreviewMouseMove="Two_OnMouseEnter">
似乎只允许内容在鼠标进入区域时更改,但在鼠标离开区域时则不会。这导致我回到原始问题的一部分:我可以强制MouseEnter
和MouseLeave
遵循隧道路由策略吗?
答案 0 :(得分:0)
它没有做任何事情,因为事件来自Button
(因此是sender
)。
这样的事情就是你要做的事情:
private void Two_OnMouseEnter(object sender, MouseEventArgs e)
{
Button b = sender as Button;
Grid g = b.Content as Grid;
Ellipse el = g.Children[0] as Ellipse;
Label l = g.Children[1] as Label;
g.Height = 200;
g.Width = 200;
el.Height = 60;
el.Width = 60;
el.Fill = Brushes.White;
l.Foreground = Brushes.Black;
}
<强>更新强>
为了更多地解释隧道策略,请考虑以下示例(为方便起见,我删除了“One”的事件处理程序):
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<Button x:Name="One" Content="ONE" Height="50" Width="Auto" />
<Button x:Name="Two">
<Grid PreviewMouseMove="Grid_PreviewMouseMove">
<Ellipse Fill="Black" Height="40" Width="40" PreviewMouseMove="Ellipse_PreviewMouseMove" />
<Label Content="TWO" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center"
PreviewMouseMove="Label_PreviewMouseMove"/>
</Grid>
</Button>
</StackPanel>
</StackPanel>
在代码隐藏中:
private void Grid_PreviewMouseMove(object sender, MouseEventArgs e)
{
Grid g = sender as Grid;
if (g != null)
{
g.Height = 200;
g.Width = 200;
}
System.Diagnostics.Debug.WriteLine("Sender: " + sender.GetType() + "; Source: " + e.Source.GetType());
}
private void Ellipse_PreviewMouseMove(object sender, MouseEventArgs e)
{
Ellipse el = sender as Ellipse;
if (el != null)
{
el.Height = 60;
el.Width = 60;
el.Fill = Brushes.White;
}
System.Diagnostics.Debug.WriteLine("Sender: " + sender.GetType() + "; Source: " + e.Source.GetType());
}
private void Label_PreviewMouseMove(object sender, MouseEventArgs e)
{
Label l = sender as Label;
if (l != null)
{
l.Foreground = Brushes.Black;
}
System.Diagnostics.Debug.WriteLine("Sender: " + sender.GetType() + "; Source: " + e.Source.GetType());
}
这些方法理论上可以重构为一种方法,应用一些逻辑来检测Type
的{{1}},但它仍然会在XAML中三次。
有一点需要注意的是sender
除非你设置Grid
属性(例如,Background
),否则不会触发自己的事件,尽管它仍然会触发Transparent
和Ellipse
开火。
另一件需要注意的事情是,当Label
触发事件时,即当您将鼠标移到Label
上时,不会调用Label
的事件处理程序。这是因为隧道策略在逻辑上沿树而不是在视觉上进行。如果您在“输出”窗口中查看消息中的“来源:”部分,您将看到我的意思。冒泡活动也是如此。
作为一般观察,具有这种策略的事情是,当事件从不同元素发射时,你的控制并不真正起作用单Ellipse
,这看起来是意图。如果你慢慢移动鼠标,你会发现Button
先发射,然后发现Ellipse
。
没有任何Label
或PreviewMouseEnter
事件,因此无论如何都无法使用隧道。