带按钮的 WPF 自定义控件

WPF Custom Control with buttons

提问人:Richard Gale 提问时间:9/1/2023 更新时间:9/1/2023 访问量:27

问:

我为我的应用程序创建了一个 WPF 自定义控件。我现在正在努力连接控件中某些控件的事件 (ToggleButtons)。

我定义了以下内容:

  • 窗口标头.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>
  • 窗口标头.xaml.cs
public partial class WindowHeader : ResourceDictionary 
{

    public WindowHeader() 
    { 
        InitializeComponent(); 
    } 
        
    public void Target_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
    -- THIS IS WHERE I WANT KNOWLEDGE OF THE COMMAND PASSED TO WindowHeader.cs
        throw new NotImplementedException();
    }
    
    public void Target_PreviewMouseUp(object sender, MouseButtonEventArgs e)
    {
        throw new NotImplementedException();
    }
}

MainWindow.xaml 中的控件声明:

<ctrl:WindowHeader TargetSelectedCommand="{Binding OutputDestinationViewModel.DestinationSelectedCommand}" />

我想做的是,当触发 Target_MouseDown 事件时,它会执行已通过 WindowHeader 传递的 ICommand TargetSelectedCommand.cs

WPF 事件 自定义控件 iCommand

评论

0赞 Andy 9/1/2023
您是否考虑过使用用户控件?

答:

1赞 Anton 9/1/2023 #1

ctrl 的 ControlTemplate 内部:WindowHeader 可以使用 TemplateBinding 来绑定依赖项属性

<ToggleButton Command="{TemplateBinding TargetSelectedCommand}"/>

但是,如果要从资源字典中的处理程序调用 TargetSelectedCommand - 则需要检索 WindowHeader 的实例

public void Target_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    var toggleButton = sender as ToggleButton;
    if (toggleButton is null) return;

    is (toggleButton.TemplatedParent is WindowHeader control)
    {
        control.TargetSelectedCommand?.Execute();
    }
    //throw new NotImplementedException();
}

评论

0赞 Richard Gale 9/1/2023
谢谢安东,这是我错过的部分,目前从处理程序调用它可能没有 100% 的意义,但是此控件中还有其他按钮需要通过处理程序重新路由非常感谢您的输入