View IsEnabled Property is not working on Xamarin Forms

Here is my Listview Inside Listview button IsEnabled Property not working,IsEnabled False not working. I followed This step but still its not working https://forums.xamarin.com/discussion/47857/setting-buttons-isenabled-to-false-does-not-disable-button Inside My ViewModel

OrderItems=PopuldateOrders();// getting List Items

<ListView x:Name="OrderItems" VerticalOptions="Fill" 
                                  BackgroundColor="White" HasUnevenRows="True" 
                                  SeparatorVisibility="None" ItemsSource="{Binding OrderItems}">
                            <ListView.ItemTemplate>
                                <DataTemplate>
                                    <ViewCell>
                                        <ContentView BackgroundColor="White">
                                            <Grid BackgroundColor="Transparent" Margin="0" VerticalOptions="FillAndExpand" x:Name="Item">
                                                <Grid.RowDefinitions>
                                                    <RowDefinition Height="*" />
                                                </Grid.RowDefinitions>
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition Width="10*"/>
                                                    <ColumnDefinition Width="18*"/>
                                                    <ColumnDefinition Width="18*"/>
                                                    <ColumnDefinition Width="17*"/>
                                                    <ColumnDefinition Width="20*"/>
                                                    <ColumnDefinition Width="17*"/>
                                                </Grid.ColumnDefinitions>
                                                <Label Text="{Binding PullSheetId}" Grid.Row="0" IsVisible="False"/>
                                                <controls:CheckBox Checked="{Binding IsChecked}" Grid.Row="0" Grid.Column="0" IsVisible="{Binding IsEnableShipBtn}" Scale=".8"/>
                                                <Label Text="{Binding KitSKU}" Grid.Row="0" Grid.Column="1" 
                                                   HorizontalTextAlignment="Center" VerticalOptions="Center" FontSize="Small" TextColor="Black"/>
                                                <Label Text="{Binding SKU}" Grid.Row="0" Grid.Column="2" 
                                                   HorizontalTextAlignment="Center" VerticalOptions="Center" FontSize="Small" TextColor="{Binding ItemColor}"/>
                                                <Label Text="{Binding ReqPackQty}" Grid.Row="0" Grid.Column="3" 
                                                   HorizontalTextAlignment="Center" VerticalOptions="Center" FontSize="Small" TextColor="Black"/>
                                                <local:EntryStyle Scale=".6" Text="{Binding ScanQuantity}" Grid.Row="0" Keyboard="Numeric"
                                                                  Grid.Column="4" HorizontalTextAlignment="Center" 
                                                                  VerticalOptions="Center" Placeholder="Qty" IsEnabled="True" x:Name="QtyEntry"
                                                                  >
                                                    <local:EntryStyle.Behaviors>
                                                        <eventToCommand:EventToCommandBehavior EventName="TextChanged"  
                                                                                               Command="{Binding Source={x:Reference OrderItems}, Path=BindingContext.ChangeItemQty}"
                                                                                                CommandParameter="{Binding Source={x:Reference Item}, Path=BindingContext}"
                                                                                               />
                                                    </local:EntryStyle.Behaviors>
                                                </local:EntryStyle>
                                                <Button Text="Ship" Scale=".6" Grid.Row="0" Grid.Column="5"  
                                                    VerticalOptions="Center" BackgroundColor="#6eb43a" TextColor="White" 
                                                    BorderRadius="20" CornerRadius="20" BorderColor="{Binding isError}" BorderWidth="3" 
                                                    MinimumWidthRequest="60"
                                                        x:Name="ShipBtn" 
                                                        Command="{Binding Source={x:Reference OrderItems}, Path=BindingContext.SubmitSingleItem}" 
                                                        IsEnabled="{Binding IsEnableShipBtn}" IsVisible="{Binding IsEnableShipBtn}"
                                                        CommandParameter="{Binding .}" 
                                                        />

                                            </Grid>
                                        </ContentView>
                                    </ViewCell>
                                </DataTemplate>
                            </ListView.ItemTemplate>
                            <ListView.Behaviors>
                                <eventToCommand:EventToCommandBehavior EventName="ItemTapped" Command="{Binding PackerItemsItemTapped}"/>
                            </ListView.Behaviors>
                        </ListView>

How to solve this?


Solution 1:

You could achieve CanExecute method in ICommand to replace the IsEnabled property of Button. You could refer to my demo.

This is a GIF of my demo.

enter image description here

Firstly, You could see MainPage.xaml. Binding the model view and set command for Buttons.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:local="clr-namespace:TestDemo"
         x:Class="TestDemo.MainPage">
<!--BindingContext from  ButtonExecuteViewModel -->
<StackLayout>
    <StackLayout.BindingContext>
       <local:ButtonExecuteViewModel/>
    </StackLayout.BindingContext>

    <Button
         Text="click me to enable following button"
         Command="{Binding NewCommand}"/>

    <Button
         Text="Cancel"
         Command="{Binding CancelCommand}"/>

</StackLayout>

Here is View Model ButtonExecuteViewModel.cs. You could see the construction method of ButtonExecuteViewModel, it set the execute and canExecute to acheve isEnable of Button.

public class ButtonExecuteViewModel : INotifyPropertyChanged
{

    bool isEditing;
    public event PropertyChangedEventHandler PropertyChanged;
    public ButtonExecuteViewModel()
    {

        NewCommand = new Command(
            execute: () =>
            {

                IsEditing = true;
                RefreshCanExecutes();
            },
            canExecute: () =>
            {
                return !IsEditing;
            });



        CancelCommand = new Command(
            execute: () =>
            {
                IsEditing = false;
                RefreshCanExecutes();
            },
            canExecute: () =>
            {
                return IsEditing;
            });

    }
    void RefreshCanExecutes()
    {
        (NewCommand as Command).ChangeCanExecute();

        (CancelCommand as Command).ChangeCanExecute();
    }

    public ICommand NewCommand { private set; get; }

    public ICommand CancelCommand { private set; get; }

    public bool IsEditing
    {
        private set { SetProperty(ref isEditing, value); }
        get { return isEditing; }
    }
    //Determine if it can be executed
    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));
    }
}