WPF Custom Control with buttons

34 Views Asked by At

I have created a WPF custom control for my application. I am now struggling to wire up the events for some of the controls in the control (ToggleButtons).

I have defined the following:

  • 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>
  • WindowHeader.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();
    }
}

Control declaration in MainWindow.xaml:

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

What I am wanting to do is when the Target_MouseDown event is fired, it executes the ICommand TargetSelectedCommand which has been passed via the WindowHeader.cs

1

There are 1 best solutions below

1
Anton On

Inside ControlTemplate of ctrl: WindowHeader dependency properties can be bounded via using TemplateBinding

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

But if you want to call TargetSelectedCommand from the handler in the resource dictionary - you need to retrieve the instance of 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();
}