如何获取发送路由事件的控件的父控件的列索引
本文关键字:控件 事件 索引 路由 何获取 获取 | 更新日期: 2023-09-27 18:20:07
我的表单上有一个带有Button
的UserControl
,单击它时,会在新行或列中添加UserControl
或不同UserControl
的另一个实例。我想做的是,当单击Button
时,找出包含Button
的UserControl
在哪个列中,然后将新的UserControl
添加到同一列中。代码如下:
++rowCount;
int currentColumn = Grid.GetColumn(e.Source as UIElement);
AnswerNode answerNode = new AnswerNode();
answerNode.buttonAddQuestionNode.MouseLeftButtonDown += AddQuestionNode_DifferentLevelEvent;
answerNode.Margin = new Thickness(0, 5, 0, 5);
RowDefinition gridRowNew = new RowDefinition();
gridRowNew.Height = new GridLength(70);
Grid.SetRow(answerNode, rowCount);
Grid.SetColumn(answerNode, currentColumn);
MainGrid.RowDefinitions.Add(gridRowNew);
MainGrid.Children.Add(answerNode);
我遇到的问题是,获取e.Source
的列索引会导致UserControl
中按钮的索引—在这种情况下为CCD_ 11—而不是CCD_ 12本身的列索引。我将如何访问UserControl
的列索引,它是被单击的Button
的父级?
如果没有一个好的、最小的、complete代码示例来清楚地说明问题,准确地显示您尝试了什么以及希望事件处理如何工作,很难确定最佳答案是什么。也就是说,从您提供的小代码和问题描述来看,听起来您订阅了错误控件对象中的事件。具体来说,您已经在Button
对象中直接声明了事件处理程序,而不是在UserControl
中订阅Button.Click
事件。
对于路由的事件,您总是可以获得事件的原始源,即通过RoutedEventArgs.OriginalSource
属性最初用信号通知事件的控件。RoutedEventArgs.Source
属性反过来将提供对事件已路由到的控制对象的引用,并且当前正在处理该事件。如果要处理UserControl
对象看到的事件,则需要从UserControl
对象而不是Button
对象订阅事件。
下面是一个简短、完整的代码示例,说明了基本技术:
XAML:
用户控制1.xaml
<UserControl x:Class="TestSO33441926RoutedEvent.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="Click here: "/>
<Button x:Name="button1" Content="Click me!" Grid.Column="1"
HorizontalAlignment="Left" VerticalAlignment="Top"
Click="Button_Click"/>
</Grid>
</UserControl>
主窗口.xaml
<Window x:Class="TestSO33441926RoutedEvent.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:TestSO33441926RoutedEvent"
Title="MainWindow" Height="350" Width="525">
<Grid x:Name="grid1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="MainWindow column 1"/>
<TextBlock Text="MainWindow column 2" Grid.Column="1"/>
<l:UserControl1 x:Name="userControl1" Grid.Column="2"
Button.Click="UserControl1_Click"/>
</Grid>
</Window>
C#:
UserControl1.xaml.cs
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
App.ReportClick((FrameworkElement)e.Source);
}
}
主窗口.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void UserControl1_Click(object sender, RoutedEventArgs e)
{
App.ReportClick((FrameworkElement)e.Source);
}
}
App.xaml.cs
public partial class App : Application
{
public static void ReportClick(
FrameworkElement frameworkElement, [CallerMemberName]string callerName = null)
{
MessageBox.Show(
"Caller name: '"" + callerName + "'"'n" +
"Sender name: '"" + frameworkElement.Name + "'"'n" +
"Sender column: " + Grid.GetColumn(frameworkElement));
}
}
由于两个事件处理程序都未将RoutedEventArgs.Handled
设置为true
,因此事件将依次发送到每个处理程序,从事件的原始源开始,然后在视觉对象图中依次向上移动到每个父级。
因此,您可以看到,当每个事件处理程序调用ReportClick()
方法时,e.Source
对象在各个事件处理程序中是不同的,这取决于该处理程序的订阅位置。
对于您自己的问题,关键在这里,在MainWindow.xaml
源代码中:
<l:UserControl1 x:Name="userControl1" Grid.Column="2"
Button.Click="UserControl1_Click"/>
请注意,Button.Click
事件是正在订阅的事件,但代码是从UserControl1
对象订阅。其结果是调用事件处理程序void UserControl1_Click(object, RoutedEventArgs)
,并将UserControl1
对象作为事件的发送方和源。
因此,当通过调用Grid.GetColumn(UIElement)
来检索事件的发送方的列索引时,返回的是UserControl1
对象的列索引,而不是事件的原始源(即实际单击的Button
对象)的列索引。
顺便说一句:在你的帖子显示的代码中,似乎有相当多的代码可以更好地实现为XAML声明。当然,在XAML中可以做的任何事情,也可以在代码背后完成。但这并不意味着这是个好主意。解决代码中的缺陷不太可能与您提出的问题直接相关,以这种方式更改实现也不会解决问题。但是,您绝对应该认真考虑更紧密地遵循WPF/XAML范式,并尽可能多地将您的实现放在XAML中