提问人:Woz9 提问时间:10/26/2023 更新时间:10/26/2023 访问量:46
C# winui 3 将事件从组件控件路由到父自定义控件
C# winui 3 route event from component control to parent custom control
问:
使用 C# winui 3 (.NET 6),我编写了一个自定义控件,该控件由 包含 an 和 .这个想法是,我可以为应用程序中的所有按钮保持一致的外观,并简化我的 xaml,因此我只需要添加 、 和 的值。CommonButtonControl
Button
Image
TextBlock
CommonButtonControl
ImageSource
Text
Command
到目前为止一切正常,但我还想添加一个事件,当组件事件被触发时,该事件将被触发。这将增加与标准控件的一致性,并允许我从中捕获事件,以便在执行任何其他操作之前执行诸如显示确认对话框之类的操作。Click
CommonButtonControl
Button Click
Button
Click
CommonButtonControl
我已将一个事件添加到我的班级中。但是,我在 a(根据本文档)中定义了 xaml,当我尝试捕获组件的事件时,它只会调用后面代码中的代码,而不是类中的代码。似乎没有任何方法可以调用该对象来告诉它组件事件已触发,以便我可以引发该事件。有什么建议吗?将 a 添加为 .Click
CommonButtonControl
CommonButtonControl
DataDictionary
Click
Button
DataDictionary
CommonButtonControl
CommonButtonControl
Button
CommonButtonControl Click
RoutedEventHandler
DependencyProperty
资源字典
<ResourceDictionary
x:Class="MyApp.Views.DataTemplatesDictionary"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyApp.Views">
<Style TargetType="local:CommonButtonControl" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:CommonButtonControl">
<Button
Command="{x:Bind Command, Mode=OneWay}"
Click="Button_Click">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="32"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Image
Grid.Column="0"
Width="32"
Height="32"
Source="{x:Bind ImageSource, Mode=OneWay}"
/>
<TextBlock
Margin="8,0,0,0"
Grid.Column="1"
VerticalAlignment="Center"
Text="{x:Bind Text, Mode=OneWay}"
Style="{ThemeResource BodyTextBlockStyle}"
/>
</Grid>
</Button>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
资源字典背后的代码
partial class DataTemplatesDictionary
{
public DataTemplatesDictionary()
{
InitializeComponent();
}
private void Button_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
//how to route this to the OnButtonClick method in CommonButtonControl?
}
}
CommonButtonControl 类
public sealed class CommonButtonControl : Control
{
#region members
private DependencyProperty TextProperty = DependencyProperty.Register(
nameof(Text),
typeof(string),
typeof(CommonButtonControl),
new PropertyMetadata(default(string)));
private DependencyProperty ImageSourceProperty = DependencyProperty.Register(
nameof(ImageSource),
typeof(ImageSource),
typeof(CommonButtonControl),
new PropertyMetadata(default(ImageSource)));
private DependencyProperty CommandProperty = DependencyProperty.Register(
nameof(Command),
typeof(ICommand),
typeof(CommonButtonControl),
new PropertyMetadata(null));
public event RoutedEventHandler Click;
#endregion
#region properties
private void OnButtonClick(object sender, RoutedEventArgs e)
{
//how do I call this method when the component button click event is raised?
Click?.Invoke(this, new());
}
public string Text
{
get => (string)GetValue(TextProperty);
set => SetValue(TextProperty, value);
}
public ImageSource ImageSource
{
get => (ImageSource)GetValue(ImageSourceProperty);
set => SetValue(ImageSourceProperty, value);
}
public ICommand Command
{
get => (ICommand)GetValue(CommandProperty);
set => SetValue(CommandProperty, value);
}
#endregion
public CommonButtonControl()
{
this.DefaultStyleKey = typeof(CommonButtonControl);
}
}
用法 1 - 通过命令 (works)
<local:CommonButtonControl
Command="{x:Bind _app.DeleteItemCommand}"
Text="Delete Item"
ImageSource="{x:Bind _app.DeleteIcon}"
/>
用法 2 - 通过点击事件(如何让它工作?
<local:CommonButtonControl
Click="CommonButtonControl_Click"
Text="Delete Item"
ImageSource="{x:Bind _app.DeleteIcon}"
/>
答:
如果你命名你的 ,让我们说“ButtonControl”,Button
<Style TargetType="local:CustomButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:CustomButton">
<Button x:Name="ButtonControl" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
然后,您可以在自定义控件类中获取它并订阅 ButtonControl 的事件:Click
自定义按钮 .cs
public sealed class CustomButton : Control
{
public CustomButton()
{
this.DefaultStyleKey = typeof(CustomButton);
}
public event RoutedEventHandler? Click;
private Button? ButtonControl { get; set; }
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (ButtonControl is not null)
{
ButtonControl.Click -= ButtonControl_Click;
}
if (GetTemplateChild(nameof(ButtonControl)) is Button button)
{
ButtonControl = button;
ButtonControl.Click += ButtonControl_Click;
}
}
private void ButtonControl_Click(object sender, RoutedEventArgs e)
{
Click?.Invoke(this, e);
}
}
评论