Controls

Button

Button is the standard action control in InkkSlinger. It supports a simple text caption out of the box, can participate in templated content, raises a bubbling Click event, and can execute commands through the shared control commanding pipeline.

Quick start

Use Text for ordinary caption buttons. That is the simplest and most direct path when you do not need a custom template.

<Button Text="Save" Width="120" Height="36" />

Handle a click in XAML

<Button Text="Run import"
        Width="140"
        Height="40"
        Click="OnRunImportClick" />
namespace InkkSlinger;

public partial class ImportView : UserControl
{
    public ImportView()
    {
        InitializeComponent();
    }

    private void OnRunImportClick(object? sender, RoutedSimpleEventArgs args)
    {
        // Perform the action here.
    }
}

Bind a command

<Button Text="Open"
        Command="{Binding OpenCommand}"
        CommandParameter="{Binding SelectedFile}" />

Default recommendation: start with Text and either Click or Command. Move to a custom template only when the button needs a different visual tree.

When to use Text vs Content

InkkSlinger's Button supports both a plain text path and a templated content path. The right choice depends on whether you are using the built-in chrome or a ControlTemplate.

Use Text

Use Text for normal caption buttons. In the non-templated path, Button renders this text directly and centers it inside the padded content area.

Use Content

Use Content when your template presents arbitrary child content, or when you need to control exactly what appears inside a ContentPresenter.

The current contract is:

  • Plain, non-templated buttons render the Text property directly.
  • Templated buttons with a ContentPresenter mirror Text into the presented content only when Content was not explicitly set.
  • If you set Content explicitly, that content wins and later Text changes do not override it.
  • If your template does not include a ContentPresenter, the template controls what appears and Button does not force text into view.
<Style x:Key="CaptionButtonStyle" TargetType="{x:Type Button}">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type Button}">
        <Border Background="{TemplateBinding Background}"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}"
                Padding="{TemplateBinding Padding}">
          <ContentPresenter HorizontalAlignment="Center"
                            VerticalAlignment="Center" />
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<Button Style="{StaticResource CaptionButtonStyle}" Text="Save" />
<Button Style="{StaticResource CaptionButtonStyle}" Content="Explicit content" Text="Ignored here" />

Input and interaction

Button exposes the same action surface whether you drive it from pointer input, access keys, or commands. Visual states such as hover and pressed are available for styling and triggers.

Pointer states

IsMouseOver and IsPressed update during pointer interaction. Use them in styles or templates to change color, border, scale, or other visual properties.

Disabled state

IsEnabled="False" prevents activation. The built-in fallback style also changes the chrome so disabled buttons read differently from active ones.

Access keys

Button enables access-key recognition by default. An AccessText element can target the button by name and invoke it through an Alt-key gesture.

AccessText example

<StackPanel>
  <AccessText Text="_Save" TargetName="SaveButton" />
  <Button x:Name="SaveButton" Text="Save" />
</StackPanel>

Button also implements the shared command source contract inherited from Control:

  • Command specifies the action to execute.
  • CommandParameter passes extra data to the command.
  • CommandTarget selects the target element when you do not want the default target resolution.
  • If the command reports CanExecute == false, Button becomes disabled automatically until the command can execute again.
<Button Text="Open document"
        Command="{StaticResource OpenCommand}"
        CommandTarget="{Binding ElementName=EditorSurface}"
        CommandParameter="{Binding SelectedDocument}" />

Styling and templating

Button is designed to be styled through normal dependency properties, implicit styles, and full templates. Most advanced visuals come from styles and template triggers rather than hard-coded control behavior.

Style the built-in chrome

<Button Text="Publish"
        Background="#1F3B57"
        Foreground="#F4FAFF"
        BorderBrush="#3EA6FF"
        BorderThickness="1"
        Padding="16,8"
        Width="160"
        Height="42" />

Apply an implicit style to every Button

<Application.Resources>
  <Style TargetType="{x:Type Button}">
    <Setter Property="Background" Value="#243140" />
    <Setter Property="Foreground" Value="#F5FBFF" />
    <Setter Property="BorderBrush" Value="#4FC7C1" />
    <Setter Property="BorderThickness" Value="1" />
    <Setter Property="Padding" Value="14,8" />
  </Style>
</Application.Resources>

Build a custom template

<Style x:Key="ActionButtonStyle" TargetType="{x:Type Button}">
  <Setter Property="Background" Value="#2A2A2A" />
  <Setter Property="Foreground" Value="#F0F0F0" />
  <Setter Property="BorderBrush" Value="#3F3F3F" />
  <Setter Property="BorderThickness" Value="1" />
  <Setter Property="Padding" Value="20,10" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type Button}">
        <Border x:Name="Chrome"
                Background="{TemplateBinding Background}"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}"
                Padding="{TemplateBinding Padding}">
          <ContentPresenter HorizontalAlignment="Center"
                            VerticalAlignment="Center" />
        </Border>
        <ControlTemplate.Triggers>
          <Trigger Property="IsMouseOver" Value="True">
            <Setter TargetName="Chrome" Property="Background" Value="#333333" />
            <Setter TargetName="Chrome" Property="BorderBrush" Value="#FF8C00" />
            <Setter Property="Foreground" Value="#FFA940" />
          </Trigger>
          <Trigger Property="IsPressed" Value="True">
            <Setter TargetName="Chrome" Property="Background" Value="#1C1C1C" />
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

Template bindings are the safest way to flow owner properties such as Background, BorderBrush, BorderThickness, and Padding into your custom visual tree.

Layout and text behavior

The non-templated Button path is intentionally simple. It draws button chrome, then centers the current text layout inside the inner content area after subtracting padding and border thickness.

  • Padding and BorderThickness both contribute to desired size.
  • TextWrapping controls whether the text stays on one line or wraps to the available width.
  • With TextWrapping="NoWrap", Button prefers its intrinsic text width plus chrome.
  • With wrapped text, Button measures against the remaining inner width after padding and border are applied.
  • If Text is empty, the button still occupies the space required by its padding and border.
<StackPanel Width="240">
  <Button Text="Single line caption"
          Margin="0,0,0,8" />

  <Button Text="This caption is long enough to wrap when the available width is constrained."
          TextWrapping="Wrap"
          Padding="12,10" />
</StackPanel>

Properties and event reference

Text and action

Text: plain caption text for the built-in render path, and the source of mirrored content for templated buttons that have not set explicit Content.

TextWrapping: controls whether text is measured and rendered as a single line or wrapped lines.

Click: bubbling routed event raised when the button is invoked.

Command, CommandParameter, CommandTarget: inherited from Control and used for command execution.

Visuals and state

Background, Foreground, BorderBrush, BorderThickness, Padding: primary styling properties for built-in and templated visuals.

IsEnabled: inherited enable/disable state. Command gating can also drive this state.

IsMouseOver, IsPressed: interaction state properties commonly used by triggers.

Patterns and examples

Toolbar action button

<Button Text="Refresh"
        Padding="10,6"
        Margin="0,0,8,0"
        Command="{Binding RefreshCommand}" />

Destructive action button style

<Style x:Key="DangerButtonStyle" TargetType="{x:Type Button}">
  <Setter Property="Background" Value="#552222" />
  <Setter Property="Foreground" Value="#FFF3F3" />
  <Setter Property="BorderBrush" Value="#D05C5C" />
  <Setter Property="BorderThickness" Value="1" />
  <Setter Property="Padding" Value="16,8" />
  <Style.Triggers>
    <Trigger Property="IsMouseOver" Value="True">
      <Setter Property="Background" Value="#6A2626" />
    </Trigger>
    <Trigger Property="IsPressed" Value="True">
      <Setter Property="Background" Value="#441919" />
    </Trigger>
  </Style.Triggers>
</Style>

<Button Text="Delete save slot"
        Style="{StaticResource DangerButtonStyle}" />

Icon and label in a custom template

<Style x:Key="IconButtonStyle" TargetType="{x:Type Button}">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type Button}">
        <Border Background="{TemplateBinding Background}"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}"
                Padding="{TemplateBinding Padding}">
          <StackPanel Orientation="Horizontal">
            <TextBlock Text="[icon]" Margin="0,0,8,0" />
            <ContentPresenter VerticalAlignment="Center" />
          </StackPanel>
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<Button Style="{StaticResource IconButtonStyle}"
        Text="Featured"
        Background="#223245"
        BorderBrush="#4FC7C1"
        BorderThickness="1"
        Padding="14,8" />

Access-key driven command

<StackPanel>
  <AccessText Text="_Open" TargetName="OpenButton" />
  <Button x:Name="OpenButton"
          Text="Open"
          Command="{StaticResource OpenCommand}" />
</StackPanel>

Routed command example

<UserControl xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <UserControl.Resources>
    <RoutedUICommand x:Key="OpenCommand" Text="_Open" />
  </UserControl.Resources>

  <Grid>
    <Button Text="Open"
            Command="{StaticResource OpenCommand}" />
  </Grid>
</UserControl>

Notes and pitfalls

Use Text first. It is the simplest path for ordinary caption buttons and matches the built-in rendering path.

Templates need a ContentPresenter. If you expect mirrored Text or explicit Content to appear inside a template, the template must present that content itself.

Commands can disable the button automatically. If your command reports that it cannot execute, the button reflects that by becoming disabled until the command changes state.

Visual polish lives in styles. Hover, pressed, and animated effects are typically created with style and template triggers. Button does not ship with built-in animation behavior.