BuckBuchanan
BuckBuchanan

Reputation: 570

Unable to disable a button which has IsEnabled bound to a property

I have a problem where I can't seem to disable a button which has IsEnabled bound to a property.

I have the following XAML:

 <Button Text="Skip" IsEnabled="{Binding SkipEnabled}" ...  />

It is being bound to this BindableProperty:

    public static readonly BindableProperty SkipEnabledProperty = BindableProperty.Create(
        propertyName: nameof(SkipEnabled), returnType: typeof(bool?), declaringType: typeof(WizardMasterPage), propertyChanged: SetSkipEnabled, 
        defaultValue: null, defaultBindingMode: BindingMode.TwoWay);

    public bool? SkipEnabled
    {
        get { return (bool?)GetValue(SkipEnabledProperty); }
        set { SetValue(SkipEnabledProperty, value); }
    }

The problem is the button is always enabled.

The propertyChanged event isn't firing on the pages where the property is set to false - presumably because it is false when the page is created, so doesn't think it has changed and hence the binding is not updated. I notice that it does fire on the pages where I set the property to True.

Has anyone else seen this? Are there any workarounds?

Note: I tried just bool as well and that didn't work either.

Thanks

Upvotes: 0

Views: 727

Answers (1)

Jessie Zhang -MSFT
Jessie Zhang -MSFT

Reputation: 13843

Is this Button included in a ContentView, right?

If yes, then you can refer to the following code. I achieved this function and I added a Button on the current page to reset the value, then the UI could refresh automatically.

ChildView.xaml.cs

public partial class ChildView : ContentView 
{
    public String YourName
    {
        get
        {
            String value = (String)GetValue(YourNameProperty);
            return value;
        }
        set
        {
            SetValue(YourNameProperty, value);
        }
    }

    public static readonly BindableProperty YourNameProperty = BindableProperty.Create(nameof(YourName)
    , typeof(String)
    , typeof(ChildView), defaultBindingMode: BindingMode.TwoWay, propertyChanged: OnYourNameChanged);

   
    public bool SkipEnabled
    {
        get
        {
            bool value = (bool)GetValue(SkipEnabledProperty);
            return value;
        }
        set
        {
            SetValue(YourNameProperty, value);
        }
    }

    public static readonly BindableProperty SkipEnabledProperty = BindableProperty.Create(nameof(SkipEnabled)
    , typeof(bool)
    , typeof(ChildView), defaultBindingMode: BindingMode.TwoWay, propertyChanged: OnYourNameChanged);

    static void OnYourNameChanged(BindableObject bindable, object oldValue, object newValue)
    {
        Console.WriteLine("-----------------> " + newValue);
    }

    
    public ChildView()
    {
        InitializeComponent();
    }
}

ChildView.xaml

<?xml version="1.0" encoding="utf-8" ?> 
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiContentViewApp.ChildView"
             x:Name="TestControlView"
             >
    <VerticalStackLayout>
        <Label   Text="{Binding Source={x:Reference TestControlView}, Path=YourName}"
            VerticalOptions="Center" 
            HorizontalOptions="Center" />

        <Button Text="Skip" IsEnabled="{Binding Source={x:Reference TestControlView}, Path=SkipEnabled}"  />

    </VerticalStackLayout>
</ContentView>

MainPage.xaml

<?xml version="1.0" encoding="utf-8" ?> 
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:mauiapp="clr-namespace:MauiContentViewApp"
             
             x:Class="MauiContentViewApp.MainPage">
    <ContentPage.BindingContext>
        <mauiapp:MyViewModel></mauiapp:MyViewModel>
    </ContentPage.BindingContext>

     <VerticalStackLayout
            Spacing="25"
            Padding="30,0"
            VerticalOptions="Center">

            <mauiapp:ChildView YourName="{Binding TestName}"  SkipEnabled="{Binding TestBoolvalue}" ></mauiapp:ChildView>

            <Button Text="reset"  Command="{Binding ResetValueCommand}"/>
     </VerticalStackLayout>

</ContentPage>

MyViewModel.cs

public class MyViewModel: INotifyPropertyChanged 
{
  
    private string _testName;
    public string TestName
    {
        set { SetProperty(ref _testName, value); }
        get { return _testName; }
    }

    private bool _testBoolValue;
    public bool TestBoolvalue
    {
        set { SetProperty(ref _testBoolValue, value); }
        get { return _testBoolValue; }
    }


    public ICommand ResetValueCommand => new Command(resetMethod);

    private void resetMethod(object obj)
    {
        TestName = "reset test string";

        TestBoolvalue = !TestBoolvalue;
    }


    public MyViewModel()
    {
        TestName = "test string";

        TestBoolvalue = false;
    }


    bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        if (Object.Equals(storage, value))
            return false;
        storage = value;
        OnPropertyChanged(propertyName);
        return true;
    }
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    public event PropertyChangedEventHandler PropertyChanged;
}

Upvotes: 0

Related Questions