WPF自定义控件中如何将ToggleButton事件绑定到传入的ICommand?
WPF自定义控件命令绑定问题
我为应用创建了一个WPF自定义控件WindowHeader,目前需要给控件内的ToggleButton关联事件逻辑。已在WindowHeader.cs中定义了TargetSelectedCommand依赖属性,在WindowHeader.xaml的控件模板里,ToggleButton绑定了PreviewMouseDown等事件,希望在Target_PreviewMouseDown触发时,执行通过WindowHeader传入的TargetSelectedCommand命令。相关代码如下:
WindowHeader.cs
public class WindowHeader : ContentControl { public static readonly DependencyProperty TargetSelectedCommandProperty = DependencyProperty.Register(nameof(TargetSelectedCommand), typeof(ICommand), typeof(WindowHeader)); public ICommand TargetSelectedCommand { get => (ICommand)GetValue(TargetSelectedCommandProperty); set => SetValue(TargetSelectedCommandProperty, value); } }
WindowHeader.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ctrl="clr-namespace:App.Windows.Lib.CustomControls" x:Class="App.Windows.Lib.Style.CustomControls.WindowHeader" x:ClassModifier="public"> <Style TargetType="{x:Type ctrl:WindowHeader}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ctrl:WindowHeader}"> <ctrl:DragArea> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Style="{DynamicResource TargetSelection_TextBlock}" Text="{TemplateBinding SelectedTargetName}" Visibility="{TemplateBinding ShowTargeting}"/> <StackPanel Grid.Column="1" Style="{DynamicResource WindowHeader_StackPanel}"> <ToggleButton PreviewMouseDown="Target_PreviewMouseDown" PreviewMouseUp="Target_PreviewMouseUp" Style="{DynamicResource Target_Button}" Visibility="{TemplateBinding ShowTargeting }" /> <ToggleButton Click="Pin_Click" Style="{DynamicResource Pin_Button}" Visibility="{TemplateBinding ShowPinning}" /> <ToggleButton Click="Resize_Click" Style="{DynamicResource Resize_Button}" Visibility="{TemplateBinding ShowResizing}"/> </StackPanel> </Grid> </ctrl:DragArea> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
WindowHeader.xaml.cs
public partial class WindowHeader : ResourceDictionary { public WindowHeader() { InitializeComponent(); } public void Target_PreviewMouseDown(object sender, MouseButtonEventArgs e) { // 此处需要获取传入WindowHeader的TargetSelectedCommand并执行 throw new NotImplementedException(); } public void Target_PreviewMouseUp(object sender, MouseButtonEventArgs e) { throw new NotImplementedException(); } }
MainWindow.xaml控件声明
<ctrl:WindowHeader TargetSelectedCommand="{Binding OutputDestinationViewModel.DestinationSelectedCommand}" />
解决方案
方法一:通过TemplatedParent获取控件实例执行命令
在事件处理方法中,通过ToggleButton的TemplatedParent找到对应的WindowHeader实例,进而获取并执行命令:
public void Target_PreviewMouseDown(object sender, MouseButtonEventArgs e) { var toggleButton = sender as ToggleButton; if (toggleButton == null) return; // 获取模板关联的WindowHeader控件实例 var windowHeader = toggleButton.TemplatedParent as WindowHeader; if (windowHeader?.TargetSelectedCommand != null && windowHeader.TargetSelectedCommand.CanExecute(null)) { // 如需传递参数,将null替换为对应参数即可 windowHeader.TargetSelectedCommand.Execute(null); } }
方法二:直接在XAML中绑定Command(更符合MVVM)
如果不需要额外的鼠标事件逻辑,可以直接在ToggleButton上绑定命令,省去事件中转步骤:
<ToggleButton Command="{TemplateBinding TargetSelectedCommand}" Style="{DynamicResource Target_Button}" Visibility="{TemplateBinding ShowTargeting }" />
注意事项
- 确保
TargetSelectedCommand的CanExecute逻辑正确,执行命令前先判断是否可执行。 - 控件模板的
TargetType必须正确设置为ctrl:WindowHeader,否则TemplateBinding无法解析依赖属性。
内容的提问来源于stack exchange,提问作者Richard Gale
相关产品推荐
相关产品推荐

