c# - 如何在 C# 中将子控件的事件绑定/包装到自定义控件的事件?
问题描述
我正在构建一个自定义控件(或模板,如果你介意的话),但我不知道如何将自定义控件内的按钮的事件(单击)绑定到自定义控件本身的 Click 事件。
我在互联网上搜索过,但有些解决方案仅适用于 WPF(包括 UWP 平台中不可用的类),有些适用于 Visual Basic,有些则不完全是我的情况等等......
这是到目前为止运行良好的代码,以实现最佳清除(请注意,我已更改项目和命名空间的名称以隐藏它,改为“SomeClass”):
自定义控件IconButton.cs:
public sealed class IconButton : Control
{
public IconButton()
{
this.DefaultStyleKey = typeof(IconButton);
}
public Boolean IconButtonIsLabelVisible
{
get { return (Boolean)GetValue(IconButtonIsLabelVisibleProperty); }
set { SetValue(IconButtonIsLabelVisibleProperty, value); }
}
public static readonly DependencyProperty IconButtonIsLabelVisibleProperty =
DependencyProperty.Register("IconButtonIsLabelVisible", typeof(Boolean), typeof(IconButton), new PropertyMetadata(true));
public String IconButtonLabel
{
get { return (String)GetValue(IconButtonLabelProperty); }
set { SetValue(IconButtonLabelProperty, value); }
}
public static readonly DependencyProperty IconButtonLabelProperty =
DependencyProperty.Register("IconButtonLabel", typeof(String), typeof(IconButton), new PropertyMetadata("Content"));
public Double IconButtonLabelMargin
{
get { return (Double)GetValue(IconButtonLabelMarginProperty); }
set { SetValue(IconButtonLabelMarginProperty, value); }
}
public static readonly DependencyProperty IconButtonLabelMarginProperty =
DependencyProperty.Register("IconButtonLabelMargin", typeof(Double), typeof(IconButton), new PropertyMetadata(10));
public Style IconButtonStyle
{
get { return (Style)GetValue(IconButtonStyleProperty); }
set { SetValue(IconButtonStyleProperty, value); }
}
public static readonly DependencyProperty IconButtonStyleProperty =
DependencyProperty.Register("IconButtonStyle", typeof(Style), typeof(IconButton), new PropertyMetadata(null));
public IconElement IconButtonIcon
{
get { return (IconElement)GetValue(IconButtonIconProperty); }
set { SetValue(IconButtonIconProperty, value); }
}
public static readonly DependencyProperty IconButtonIconProperty =
DependencyProperty.Register("IconButtonIcon", typeof(IconElement), typeof(IconButton), new PropertyMetadata(0));
}
通用 xaml 模板文件Generic.xaml:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:SomeClass.Controls">
<Style TargetType="local:IconButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:IconButton">
<Button x:Name="ClickButton" Style="{TemplateBinding IconButtonStyle}" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" Command="{TemplateBinding Command}" CommandParameter="{TemplateBinding CommandParameter}">
<Grid Margin="{TemplateBinding Padding}">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ContentPresenter x:Name="Content"
Content="{TemplateBinding IconButtonIcon}"
Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center"/>
<Grid Grid.Column="1" Width="{TemplateBinding IconButtonLabelMargin}"/>
<TextBlock Grid.Column="2" Text="{TemplateBinding IconButtonLabel}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center"/>
</Grid>
</Button>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
还有MainPage.xaml,我想在其中使用 IconButton:
<Page
x:Class="SomeClass"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:SomeClass"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:testControls="using:SomeClass.Controls"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<testControls:IconButton x:Name="TestButton" Click"?" IconButtonLabelMargin="5" HorizontalAlignment="Center" Foreground="Aqua" VerticalAlignment="Center" Background="Transparent" >
<testControls:IconButton.IconButtonIcon>
<SymbolIcon Symbol="Preview"/>
</testControls:IconButton.IconButtonIcon>
</testControls:IconButton>
</Grid>
因此,鉴于此代码,我想以某种方式将 IconButton 的 xaml 模板中 ClickButton 的 Click 事件绑定到 IconButton 控件本身的默认 Click 事件,以便它可以通过简单地在主页中轻松使用指定 Click 事件。
谢谢你的好意和关注。
此致。
解决方案
这样做需要覆盖控件中的OnApplyTemplate
方法,在控件中找到命名的模板部分,并在包装器上引发事件。
在您的自定义控件中:
ButtonBase clickButtonPart = null;
public const string ClickButtonTemplatePartName = "ClickButton";
public event EventHandler Click;
protected override void OnApplyTemplate()
{
// In case the template changes, you want to stop listening to the
// old button's Click event.
if (clickButtonPart != null)
{
clickButtonPart.Click -= ClickForwarder;
clickButtonPart = null;
}
// Find the template child with the special name. It can be any kind
// of ButtonBase in this example.
clickButtonPart = GetTemplateChild(ClickButtonTemplatePartName) as ButtonBase;
// Add a handler to its Click event that simply forwards it on to our
// Click event.
if (clickButtonPart != null)
{
clickButtonPart.Click += ClickForwarder;
}
}
private void ClickForwarder(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
Click?.Invoke(this, null);
}
推荐阅读
- azureservicebus - Azure 服务总线虚拟网络已添加到防火墙,但仍无法获得 401 Ip 以连接到终结点
- macos - 如何提取在 MAC OS 中拆分为多个部分的压缩文件夹
- r - 如何将对象分配给函数的输出?
- angular - 角度报告当前路由和参数到任何组件?
- r - 使用源代码时在 ShinyApp 中找不到函数
- python - TypeError:“类型”类型的参数不可迭代
- c# - Azure 部署后 ASP.NET Core MVC webapp 错误
- typescript - TypeScript:可选的合并类型
- sql - 使用 Postgres,如果为 NULL,我如何使用 UPDATE 插入新的 jsonb 值,或者如果值已经存在,如何修改 json?
- c# - 无法使用单例“IMyCustomThing”中的范围服务“IHttpContextAccessor”