Home > Net >  wpf - A multistage button
wpf - A multistage button

Time:08-01

I want to implement a button, that have 4 stage (Stage1/Stage2/Stage3/Stage4) and I want to click on it, the text and style will change (Stage1 -> Stage2 -> Stage3 -> Stage4 -> Stage1 -> ....)

Here is my XAML button code.

<ControlTemplate x:Key="StageButton" TargetType="{x:Type Button}">
    <Button 
        Width="102"
        Tag="1"
        Click="Hello_Click"
        BorderThickness="0"
        Background="Transparent"
        Cursor="Hand">
        <Border
            BorderThickness="2"
            BorderBrush="Gray"
            CornerRadius="10"
            Background="Green"
            Width="100"
            Height="20"
            >
            <TextBlock 
                Width="100"
                Foreground="White"
                FontWeight="Bold"
                FontSize="12" 
                Padding="14 1 0 0"
                Text="Stage1"
                />
        </Border>
    </Button>
</ControlTemplate>

Thanks for help

CodePudding user response:

        <ControlTemplate 
            x:Key="ReconStatus" 
            TargetType="{x:Type Button}">
            <Button
                Width="102"
                Tag="1"
                Click="Hello_Click"
                BorderThickness="0"
                Background="Transparent"
                Cursor="Hand">
                <Border
                    BorderThickness="2"
                    BorderBrush="LightGray"
                    CornerRadius="10"
                    Background="Green"
                    Width="100"
                    Height="20"
                    >
                    <TextBlock 
                        Width="100"
                        Foreground="White"
                        FontWeight="Bold"
                        FontSize="12" 
                        TextAlignment="Center"
                        Text=""/>
                </Border>
            </Button>
        </ControlTemplate>
private void Hello_Click(object sender, RoutedEventArgs e)
{
    Button bu = sender as Button;

    var stage = bu.Tag;

    Border border = bu.Content as Border;
    TextBlock tb = border.Child as TextBlock;

    switch (stage)
    {
        case "1":
            tb.Text = "Stage2";
            border.Background = (SolidColorBrush)new BrushConverter().ConvertFromString(Colors.DodgerBlue.ToString());
            bu.Tag = "2";
            break;
        case "2":
            tb.Text = "Stage3";
            border.Background = (SolidColorBrush)new BrushConverter().ConvertFromString(Colors.Green.ToString());
            bu.Tag = "3";
            break;
        case "3":
            tb.Text = "Stage4";
            border.Background = (SolidColorBrush)new BrushConverter().ConvertFromString(Colors.DimGray.ToString());
            bu.Tag = "4";
            break;
        case "4":
            tb.Text = "Stage1";
            border.Background = (SolidColorBrush)new BrushConverter().ConvertFromString("#c42a1c");
            bu.Tag = "1";
            break;
    }
}

This code work, but as @emoacht said, it nested Button object

CodePudding user response:

You can make a custom Button with incremental stage (starting at 1) functionality:

using System;
using System.Windows;
using System.Windows.Controls;

public class StagedButton : Button
{
    public int Stage
    {
        get { return (int)GetValue(StageProperty); }
        set { SetValue(StageProperty, value); }
    }
    public static readonly DependencyProperty StageProperty =
        DependencyProperty.Register("Stage", typeof(int), typeof(StagedButton),
            new FrameworkPropertyMetadata(1, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, null,
                (d, baseValue) => Math.Min(((StagedButton)d).StageCount, Math.Max(1, (int)baseValue))));

    public int StageCount
    {
        get { return (int)GetValue(StageCountProperty); }
        set { SetValue(StageCountProperty, value); }
    }
    public static readonly DependencyProperty StageCountProperty =
        DependencyProperty.Register("StageCount", typeof(int), typeof(StagedButton),
            new PropertyMetadata(1, null,
                (d, baseValue) => Math.Max(1, (int)baseValue)));

    protected override void OnClick()
    {
        var stage = Stage;
        Stage = (  stage <= StageCount) ? stage : 1;

        base.OnClick();
    }
}

StageCount is the number of stages. (d, baseValue) => ... part is to filter out invalid values.

Then define a Style for this Button.

<Style x:Key="StagedButtonStyle" TargetType="{x:Type local:StagedButton}">
    <Setter Property="Width" Value="100"/>
    <Setter Property="Height" Value="20"/>
    <Setter Property="BorderThickness" Value="2"/>
    <Setter Property="BorderBrush" Value="LightGray"/>
    <Setter Property="Background" Value="#c42a1c"/>
    <Setter Property="Foreground" Value="White"/>
    <Setter Property="TextElement.FontWeight" Value="Bold"/>
    <Setter Property="TextElement.FontSize" Value="12"/>
    <Setter Property="Cursor" Value="Hand"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:StagedButton}">
                <Border BorderThickness="{TemplateBinding BorderThickness}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        Background="{TemplateBinding Background}"
                        CornerRadius="10">
                    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                      VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <!-- Set 4 to StageCount. -->
    <Setter Property="StageCount" Value="4"/>
    <Style.Triggers>
        <!-- Define Background for each Stage (up to 4) except default one. -->
        <Trigger Property="Stage" Value="2">
            <Setter Property="Background" Value="DodgerBlue"/>
        </Trigger>
        <Trigger Property="Stage" Value="3">
            <Setter Property="Background" Value="Green"/>
        </Trigger>
        <Trigger Property="Stage" Value="4">
            <Setter Property="Background" Value="DimGray"/>
        </Trigger>
    </Style.Triggers>
</Style>

You can increase the number of stages if you wish.

Its usage will be as follows:

<local:StagedButton Style="{StaticResource StagedButtonStyle}">
    <TextBlock Text="{Binding Stage, RelativeSource={RelativeSource AncestorType={x:Type local:StagedButton}}, StringFormat=Stage {0}}"/>
</local:StagedButton>
  • Related