[PRISM] Why my button is enable whereas my command should be false!

voidstreamvoidstream FRMember ✭✭✭
edited January 2017 in Xamarin.Forms

Hello,

I only want that my update button is active if entries are edited AND it's not the first load.
When i go on my page, data is loaded in entries and IsEdited switch to True, result my update button is active.
I have try to switch IsEdited = False; after the data load but it's not work...
Come on @NMackay ! :smile:

Best regards

My XAML:

            <StackLayout Grid.Row="0" Margin="20, 0, 20, 20" >
                <Label Style="{DynamicResource FormLabel}" Text="Nom"/>
                <Entry Style="{DynamicResource FormEntry}" Text="{Binding Lastname}" Keyboard="Default"/>
                <Label Style="{DynamicResource FormLabel}" Text="Prénom"/>
                <Entry Style="{DynamicResource FormEntry}" Text="{Binding Firstname}" Keyboard="Default"/>
                <Label Style="{DynamicResource FormLabel}" Text="Adresse électronique"/>
                <Entry Style="{DynamicResource FormEntry}" Text="{Binding Email}" Keyboard="Email"/>
                <Label Style="{DynamicResource FormLabel}" Text="Téléphone"/>
                <Entry Style="{DynamicResource FormEntry}" Text="{Binding Phone}" Keyboard="Telephone"/>
            </StackLayout>
            <StackLayout Grid.Row="1" Style="{DynamicResource BotActionBar}">
                <Button Style="{DynamicResource FormButton}" Text="Mettre à jour" Command="{Binding UpdateCommand}" HorizontalOptions="EndAndExpand"/>
            </StackLayout>

My ViewModel:

    public class ProfileEditViewModel : BindableBase
    {
        #region // Fields
        private bool _isUpdating;
        private bool _isEdited;
        private string _lastname;
        private string _firstname;
        private string _email;
        private string _phone;
        #endregion

        #region // Properties
        public INavigationService NavigationService { get; private set; }
        public DelegateCommand<string> NavigateCommand { get; private set; }
        public DelegateCommand UpdateCommand { get; private set; }

        public bool IsUpdating { get { return _isUpdating; } set { SetProperty(ref _isUpdating, value); } }
        public bool IsEdited { get { return _isEdited; } set { SetProperty(ref _isEdited, value); } }
        public string Lastname { get { return _lastname; } set { SetProperty(ref _lastname, value.NameFormat()); IsEdited = true; } }
        public string Firstname { get { return _firstname; } set { SetProperty(ref _firstname, value.NameFormat()); IsEdited = true; } }
        public string Email { get { return _email; } set { SetProperty(ref _email, value.ToLower()); IsEdited = true; } }
        public string Phone { get { return _phone; } set { SetProperty(ref _phone, value.PhoneFormat()); IsEdited = true; } }
        #endregion

        #region // Methods
        public ProfileEditViewModel(INavigationService navigationService)
        {
            NavigationService = navigationService;
            NavigateCommand = new DelegateCommand<string>(Navigate);
            UpdateCommand = new DelegateCommand(Update).ObservesCanExecute((p) => IsEdited);

            Lastname = App.API.User.Lastname;
            Firstname = App.API.User.Firstname;
            Email = App.API.User.Email;
            Phone = App.API.User.Phone;
            IsEdited = false;
        }

        private async void Update()
        {
            IsUpdating = true;
            if (await App.API.EditUserInfos(Lastname, Firstname, Email, Phone))
            {
                App.API.User.Lastname = Lastname;
                App.API.User.Firstname = Firstname;
                App.API.User.Email = Email;
                App.API.User.Phone = Phone;
                IsEdited = false;
            }
            IsUpdating = false;
        }

        private void Navigate(string s)
        {
            NavigationService.NavigateAsync(s);
        }
        #endregion
    }

Best regards

Best Answer

Answers

  • NMackayNMackay GBInsider, University mod
    edited January 2017

    @TonyPinot

    I'm not exactly clear how your determining if it's 1st load but you can add extra conditional execution checks like i do in this example

    public DelegateCommand SearchCommand => new DelegateCommand(RefreshModel, () => !Busy && SearchTerm.Length > 1).ObservesProperty(() => Busy).ObservesProperty(() => SearchTerm);
    

    Or maybe this approach

    public DelegateCommand<OrderSearchResult> SelectCommand => new DelegateCommand<OrderSearchResult>(SelectOrder, (s) => !Busy)
                                                                        .ObservesProperty(() => Busy)
                                                                        .ObservesCanExecute((vm) => CanNavigate);
    
  • voidstreamvoidstream FRMember ✭✭✭
    edited January 2017

    @NMackay Thanks for reply, i discover a new syntaxe for command declaration

    I create a new property(IsFirstLoading), IsEdited = !IsFirstLoading
    IsFirstLoading start true in contructor and end false. If i delete "IsFirstLoading = false", my button is not active.

    This new code don't works:

    private bool _isFirstLoading;
    public bool IsFirstLoading { get { return _isFirstLoading; } set { SetProperty(ref _isFirstLoading, value); } }
    
    public DelegateCommand UpdateCommand => new DelegateCommand(Update).ObservesCanExecute((p) => IsEdited);
    
    public string Lastname { get { return _lastname; } set { SetProperty(ref _lastname, value.NameFormat()); IsEdited = !IsFirstLoading; } }
    public string Firstname { get { return _firstname; } set { SetProperty(ref _firstname, value.NameFormat()); IsEdited = !IsFirstLoading; } }
    public string Email { get { return _email; } set { SetProperty(ref _email, value.ToLower()); IsEdited = !IsFirstLoading; } }
    public string Phone { get { return _phone; } set { SetProperty(ref _phone, value.PhoneFormat()); IsEdited = !IsFirstLoading; } }
    
    public ProfileEditViewModel(INavigationService navigationService)
    {
        NavigationService = navigationService;
    
        IsFirstLoading = true;
        Lastname = App.API.User.Lastname;
        Firstname = App.API.User.Firstname;
        Email = App.API.User.Email;
        Phone = App.API.User.Phone;
        IsFirstLoading = false;
    }
    

    Same problem with:

    public DelegateCommand UpdateCommand => new DelegateCommand(Update,() => !IsFirstLoading).ObservesProperty(() => IsEdited);
    
  • NMackayNMackay GBInsider, University mod

    @BrianLagunas

    Is my syntax wrong? just thought I'd double check :smile:

  • BrianLagunasBrianLagunas USInsider ✭✭✭

    @NMackay Yes, it is. If you want to use the new C# syntax sugar, then it should look like the snippet I provided above. Otherwise, every time the command property is fetched (getter called), it will return a new instance which means that your CanExecuteChanged event (ObservesProeprty) will never work properly.

  • NMackayNMackay GBInsider, University mod
    edited January 2017

    @BrianLagunas

    Thanks for the explanation, it explains one or two issues I was having, I got the snippet from a SO post I think. It wasn't the way I defined RelayComamnds so I should have looked at it a bit closer I guess.

  • voidstreamvoidstream FRMember ✭✭✭
    edited January 2017

    @BrianLagunas @NMackay

    Hum with the debug mode when i leave the constructor "IsEdited" is false but just after i go in CanUpdate and "IsEdited" is true...
    [EDIT] Okay i understand now, between Constructor and CanUpdate, my properties are set a second time! That why "IsEdited" is allways true!
    But now, why my properties are set 2 times with the same values?

            //public DelegateCommand UpdateCommand => new DelegateCommand(Update).ObservesCanExecute((p) => IsEdited);
            private DelegateCommand _updateCommand;
            public DelegateCommand UpdateCommand => _updateCommand ?? (_updateCommand = new DelegateCommand(Update,CanUpdate)
                .ObservesProperty(() => IsFirstLoading)
                .ObservesProperty(() => IsEdited));
    
            public bool IsFirstLoading { get { return _isFirstLoading; } set { SetProperty(ref _isFirstLoading, value); } }
            public bool IsEdited { get { return _isEdited; } set { SetProperty(ref _isEdited, value); } }
            public string Lastname { get { return _lastname; } set { SetProperty(ref _lastname, value.NameFormat()); if (!IsFirstLoading) { IsEdited = true; } } }
            public string Firstname { get { return _firstname; } set { SetProperty(ref _firstname, value.NameFormat()); if (!IsFirstLoading) { IsEdited = true; } } }
            public string Email { get { return _email; } set { SetProperty(ref _email, value.ToLower()); if (!IsFirstLoading) { IsEdited = true; } } }
            public string Phone { get { return _phone; } set { SetProperty(ref _phone, value.PhoneFormat()); if (!IsFirstLoading) { IsEdited = true; } } }
            #endregion
    
            #region // Methods
            public ProfileEditViewModel(INavigationService navigationService)
            {
                NavigationService = navigationService;
    
                IsFirstLoading = true;
                Lastname = App.API.User.Lastname;
                Firstname = App.API.User.Firstname;
                Email = App.API.User.Email;
                Phone = App.API.User.Phone;
                IsEdited = false;
                IsFirstLoading = false;
            }
            private bool CanUpdate()
            {
                bool b = IsEdited && !IsFirstLoading;
                return b;
            }
    
  • NMackayNMackay GBInsider, University mod

    @BrianLagunas

    Thanks for the tip, this works as expected now.

    private DelegateCommand _clearCommand;
            public DelegateCommand ClearCommand => _clearCommand ?? (_clearCommand = new DelegateCommand(ClearPage, ()=> !Busy && !string.IsNullOrEmpty(Uid) 
                                                                                         || !string.IsNullOrEmpty(Pwd)))
                                    .ObservesProperty(() => Busy)
                                    .ObservesProperty(() => Uid)
                                    .ObservesProperty(() => Pwd);
    
Sign In or Register to comment.