从外部 UserControl 中的 WPF 按钮捕获事件
Catch event from WPF Button in external UserControl
为了使WPF项目更清晰,我决定在外部UserControl中定义ItemsControl的行布局。
这是显示列表的主页:
<ScrollViewer Name="ItemsScroll" Grid.Row="1" VerticalScrollBarVisibility="Auto">
<ItemsControl Name="ItemsList">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type local:OptionSetItem}">
<local.controls:OptionItemControl />
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>
</ScrollViewer>
local.controls:OptionItemControl
在另一个文件中定义:
<UserControl x:Class="OptionSetManager.Controls.OptionItemControl"
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="100" d:DesignWidth="300">
<Grid Height="30">
<Grid.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis" />
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="7*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<TextBlock Name="ItemId" Grid.Column="0" VerticalAlignment="Center" TextAlignment="Center" FontSize="16" Foreground="DarkGray" Text="{Binding Id}" />
<TextBox Name="ItemText" Grid.Column="1" VerticalContentAlignment="Center" FontSize="16" Text="{Binding Text}" BorderBrush="{x:Null}" Background="#FFF0F0F0" IsReadOnly="{Binding ToBeDeleted}" HorizontalAlignment="Right" Width="210" />
<Button Name="DeleteExistingButton" Grid.Column="2" Click="DeleteExistingButton_Click" Tag="{Binding Id}" Cursor="Hand" ToolTip="Mark as deleted">
<Button.Template>
<ControlTemplate>
<Image Source="/Assets/delete.png"/>
</ControlTemplate>
</Button.Template>
</Button>
<Rectangle Fill="Red" Height="3" Margin="15,0" Grid.Column="0" Visibility="{Binding ToBeDeleted, Converter={StaticResource BoolToVis}}"></Rectangle>
</Grid>
</UserControl>
如您所见,自定义控件包含一个 DeleteExistingButton
可触发 Click 事件。目标是从列表所在的主页捕获此事件。
我遵循了 this 等一些答案,但我卡在某个点上了,稍后我会告诉你。首先,这是 UserControl 背后的代码:
namespace OptionSetManager.Controls
{
public partial class OptionItemControl : UserControl
{
public event EventHandler OnDeleteExistingButtonClick;
public OptionItemControl()
{
InitializeComponent();
}
private void DeleteExistingButton_Click(object sender, RoutedEventArgs e)
{
if (this.OnDeleteExistingButtonClick != null) OnDeleteExistingButtonClick(this, e);
}
}
}
我在这里将事件传播到处理程序(如果存在)。我应该从主页附上它,但显然我不能做
OptionItemControl.OnDeleteExistingButtonClick += new EventHandler(UserControl_ButtonClick);
因为OptionItemControl
不是对象的实例,而只是DataTemplate中的一个元素。
我错过了什么?
您可以使用以下语法在 DataTemplate 中处理 OnDeleteExistingButtonClick 事件:
<DataTemplate DataType="{x:Type local:OptionSetItem}">
<local.controls:OptionItemControl OnDeleteExistingButtonClick="YourHandler"/>
</DataTemplate>
注意:您应该将事件命名为 DeleteExistingButtonClick 而不是 OnDeleteExistingButtonClick(这是约定,引发事件的函数应命名为 OnYourEvent 或 RaiseYourEvent)
为了使WPF项目更清晰,我决定在外部UserControl中定义ItemsControl的行布局。
这是显示列表的主页:
<ScrollViewer Name="ItemsScroll" Grid.Row="1" VerticalScrollBarVisibility="Auto">
<ItemsControl Name="ItemsList">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type local:OptionSetItem}">
<local.controls:OptionItemControl />
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>
</ScrollViewer>
local.controls:OptionItemControl
在另一个文件中定义:
<UserControl x:Class="OptionSetManager.Controls.OptionItemControl"
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="100" d:DesignWidth="300">
<Grid Height="30">
<Grid.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis" />
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="7*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<TextBlock Name="ItemId" Grid.Column="0" VerticalAlignment="Center" TextAlignment="Center" FontSize="16" Foreground="DarkGray" Text="{Binding Id}" />
<TextBox Name="ItemText" Grid.Column="1" VerticalContentAlignment="Center" FontSize="16" Text="{Binding Text}" BorderBrush="{x:Null}" Background="#FFF0F0F0" IsReadOnly="{Binding ToBeDeleted}" HorizontalAlignment="Right" Width="210" />
<Button Name="DeleteExistingButton" Grid.Column="2" Click="DeleteExistingButton_Click" Tag="{Binding Id}" Cursor="Hand" ToolTip="Mark as deleted">
<Button.Template>
<ControlTemplate>
<Image Source="/Assets/delete.png"/>
</ControlTemplate>
</Button.Template>
</Button>
<Rectangle Fill="Red" Height="3" Margin="15,0" Grid.Column="0" Visibility="{Binding ToBeDeleted, Converter={StaticResource BoolToVis}}"></Rectangle>
</Grid>
</UserControl>
如您所见,自定义控件包含一个 DeleteExistingButton
可触发 Click 事件。目标是从列表所在的主页捕获此事件。
我遵循了 this 等一些答案,但我卡在某个点上了,稍后我会告诉你。首先,这是 UserControl 背后的代码:
namespace OptionSetManager.Controls
{
public partial class OptionItemControl : UserControl
{
public event EventHandler OnDeleteExistingButtonClick;
public OptionItemControl()
{
InitializeComponent();
}
private void DeleteExistingButton_Click(object sender, RoutedEventArgs e)
{
if (this.OnDeleteExistingButtonClick != null) OnDeleteExistingButtonClick(this, e);
}
}
}
我在这里将事件传播到处理程序(如果存在)。我应该从主页附上它,但显然我不能做
OptionItemControl.OnDeleteExistingButtonClick += new EventHandler(UserControl_ButtonClick);
因为OptionItemControl
不是对象的实例,而只是DataTemplate中的一个元素。
我错过了什么?
您可以使用以下语法在 DataTemplate 中处理 OnDeleteExistingButtonClick 事件:
<DataTemplate DataType="{x:Type local:OptionSetItem}">
<local.controls:OptionItemControl OnDeleteExistingButtonClick="YourHandler"/>
</DataTemplate>
注意:您应该将事件命名为 DeleteExistingButtonClick 而不是 OnDeleteExistingButtonClick(这是约定,引发事件的函数应命名为 OnYourEvent 或 RaiseYourEvent)