Search code examples
c#avaloniauiavalonia

Avalonia TemplatedControl handle onclick


I want to make a custom templated control that can handle an onclick from a button to change a value Lets say for example I have a control that can reset its value (Not my actual use case)

The axaml would look like this:

<Style Selector="controls|ResetInput">
    <!-- Set Defaults -->
    <Setter Property="Template">
        <ControlTemplate>
            <StackPanel>
                <Button Click="reset">Reset</Button>
                <TextBox Text="{TemplateBinding Value}" />
            </StackPanel>
        </ControlTemplate>
    </Setter>
</Style>

And the code behind would have this:

public class ResetInput : ContentControl
{
    public static readonly StyledProperty<string?> ValueProperty = AvaloniaProperty.Register<ResetInput, string?>(nameof(Value), defaultBindingMode: Avalonia.Data.BindingMode.TwoWay);

    public string? Value
    {
        get { return GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }

    public ResetInput()
    {
    }

    public void reset(object? sender, RoutedEventArgs e)
    {
        Value = "";
    }
}

But when I try this I get the message "Unable to find suitable setter or adder for property Click of type Avalonia.Controls:Avalonia.Controls.Button for argument System.Runtime:System.String, available setter parameter lists are:" How are you supposed to do this


Solution

  • I figured out a way to do it that I liked in the xaml I name the button to what I want to use in the code behind (documentation says it has to start with "PART_") like so:

    <Style Selector="controls|ResetInput">
        <Setter Property="Template">
            <ControlTemplate>
                <StackPanel>
                    <Button Name="PART_RstBtn">Reset</Button>
                    <TextBox Text="{TemplateBinding Value}" />
                </StackPanel>
            </ControlTemplate>
        </Setter>
    </Style>
    

    And in the code behind I added a TemplatePart, a button property and override OnApplyTemplate where I can find the button and add a click handler like so:

    [TemplatePart("PART_RstBtn", typeof(Button))]
    public class ResetInput : ContentControl
    {
        public static readonly StyledProperty<string?> ValueProperty = AvaloniaProperty.Register<ResetInput, string?>(nameof(Value), defaultBindingMode: Avalonia.Data.BindingMode.TwoWay);
    
        public string? Value
        {
            get { return GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }
    
        private Button? BtnReset { get; set; }
    
        protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
        {
            BtnReset = e.NameScope.Find<Button>("PART_RstBtn");
            if (BtnUp != null)
            {
                BtnUp.Click += Reset;
            }
        }
    
        private void Reset(object? sender, RoutedEventArgs e)
        {
            Value = "";
        }
    }