Search code examples
user-interfacebuttontextboxavaloniauiavalonia

How to make button enabled in AvaloniaUI depending on Textbox value


I'm new to Avalonia, so my code should be pretty basic. I have 1 window with 1 panel in it that is:

<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center" Width="300">
<TextBlock Text="{Binding Greeting}" />

<TextBox Text="{Binding Name}"/>
<Button Content="Say HI" Click="OnButtonClicked" IsEnabled="{Binding Enable}"/>

That panel has TextBlock, TextBox, and button. The button is not enabled by default. My question is, how can I enable it when the value of textBox is changes. Here is my Model class that already has some basic logic in it:

class HelloViewModel : INotifyPropertyChanged
{
    private string greeting = "";
    private string name = "";
    public bool Enable = false;

    public string Greeting
    {
        get => greeting;

        set
        {
            if (value != greeting)
            {
                greeting = value;
                OnPropertyChanged();
                Enable = true;
            }
        }
    }

    public string Name
    {
        get => name;
        set
        {
            if(value != name)
            {
                name = value;
                OnPropertyChanged();
                Enable = true;
            }
        }
    }

   

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Solution

  • If you create a new MVVM Project from the Avalonia Template you will get a ViewModelBase class. I would suggest to use that.

    ViewModelBase.cs

    public class ViewModelBase : ReactiveObject
    {
    }
    

    MainWindowViewModel.cs

    public class MainWindowViewModel : ViewModelBase
    {
        public string Greeting {
            get => "Welcome to Avalonia.";
        }
    
        private bool enable = false;
        public bool Enable
        {
            get => enable;
            set => this.RaiseAndSetIfChanged(ref enable, value);
        }
    
        private string name = string.Empty;
        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                this.RaiseAndSetIfChanged(ref name, value);
                Enable = true;
            }
        }
    }
    

    Just to make sure, the MainWindow.xaml

      <Design.DataContext>
          <vm:MainWindowViewModel/>
      </Design.DataContext>
    
    <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center" Width="300">
      <TextBlock Text="{Binding Greeting}" />
    
      <TextBox Text="{Binding Name}"/>
      <Button Content="Say HI" Click="OnButtonClicked" IsEnabled="{Binding Enable}"/>
    </StackPanel>
    

    Where vm is xmlns:vm="clr-namespace:<YourNamespaceContainingTheViewModel>;assembly=<YourProject>"

    Additional infos and how to set the ViewModel from CodeBehind can be found here.

    Edit

    If you only want to enable the button, when a specific text is set, you can add a condition like that:

    public string Name
    {
      get
        {
            return name;
        }
        set
        {
            this.RaiseAndSetIfChanged(ref name, value);
            if (Name == Greeting)
            {
                Enable = true;
            }
            else
            {
                Enable = false;
            }
        }
    }