首页 > 解决方案 > Xamarin 按钮未启用

问题描述

用户注册页面有一个保存工具栏按钮。它总是被禁用。在屏幕上更改参数时不会调用 CanExecute 方法。当用户名和密码不为空且 PW 和 Confirmpassword 字段匹配时,应通过 CanExecute 方法启用 Save 按钮。当对三个字段中的任何一个进行更改时,不会调用 CanExecute 方法。

当在三个字段(用户名、密码和 ConfirmPassword )中的任何一个字段中输入内容时,为什么不为 registerButton 调用 CanExecute 方法 OnPropertyChanged 方法被调用以对这三个字段进行任何更改,但显然外部代码不是检测到发生了变化。这是某种范围问题吗?

如有必要,整个项目都可用。

吉姆·德宾

Here is the xaml code

<?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:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class=*"ButtonTest.RegisterPage"*>
    <ContentPage.ToolbarItems>
        **<ToolbarItem x:Name="registerButton"
            Text="Save"
            Command="{Binding RegisterCommand}"
            CommandParameter="{Binding Password}"/>**
    </ContentPage.ToolbarItems>
    <ContentPage.Content>
        <ScrollView Orientation="Vertical">
            <StackLayout x:Name="containerStackLayout"
                     VerticalOptions="FillAndExpand"                     
                     Margin="20">
                <Label Text="Registration"
                       FontSize="Large"
                       HorizontalOptions="Center"
                       FontAttributes="Bold"></Label>
                <Entry x:Name="UserName"
                    Placeholder="User Name"
                    Text="{Binding UserName, Mode=TwoWay}"
                    Keyboard="Text"/>
                <Entry x:Name="PasswordEntry"
                    Placeholder="Password"
                    Text="{Binding PW, Mode=TwoWay}"
                    IsPassword="True"/>
                <Entry x:Name="confirmPasswwordEntry"
                    Placeholder="Confirm Password"
                    Text="{Binding ConfirmPassword, Mode=TwoWay}"
                    IsPassword="True"/>
                <Entry x:Name="Email"
                    Placeholder="Email"
                    Text="{Binding Email, Mode=TwoWay}"
                    Keyboard="Email"/>
            </StackLayout>
        </ScrollView>
    </ContentPage.Content>
</ContentPage>

viewModel code 

using ButtonTest.Model;
using System.ComponentModel;
using ButtonTest.ViewModel.Commands;

namespace ButtonTest.ViewModel
{
    public class RegisterPageVM : INotifyPropertyChanged
    {
        public RegisterCommand RegisterCommand { get; set; }

        private Password user;
        public Password User
        {
            get { return user; }
            set
            {
                user = value;
                OnPropertyChanged("User");
            }
        }


        private string username;
        public string UserName
        {
            get { return username; }
            set
            {
                username = value;
                User = new Password()
                {
                    UserName = this.UserName,
                    PW = this.PW,
                    ConfirmPassword = this.ConfirmPassword
                };
                OnPropertyChanged("UserName");
            }
        }

        private string pw;
        public string PW
        {
            get { return pw; }
            set
            {
                pw = value;
                User = new Password()
                {
                    UserName = this.UserName,
                    PW = this.PW,
                    ConfirmPassword = this.ConfirmPassword
                };
                OnPropertyChanged("PW");
            }
        }

        private string confirmpassword;
        public string ConfirmPassword
        {
            get { return confirmpassword; }
            set
            {
                confirmpassword = value;
                User = new Password()
                {
                    UserName = this.UserName,
                    PW = this.PW,
                    ConfirmPassword = this.ConfirmPassword
                };
                OnPropertyChanged("ConfirmPassword");
            }
        }
        public RegisterPageVM()
        {
            RegisterCommand = new RegisterCommand(this);
            //User = new Password();
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        public void Register(Password user)
        {
            Password.Register(user);
        }
    }
}

Here is the command code

using System;
using System.Windows.Input;
using ButtonTest.Model;

namespace ButtonTest.ViewModel.Commands
{
    public class RegisterCommand : ICommand
    {
        private RegisterPageVM viewModel;

        public RegisterCommand(RegisterPageVM viewModel)
        {
            this.viewModel = viewModel;
        }

        public event EventHandler CanExecuteChanged;

        public bool CanExecute(object parameter)
        {
            Password user = (Password)parameter;
            if (user != null)
            {
                if (user.PW == user.ConfirmPassword)
                {
                    if (string.IsNullOrEmpty(user.UserName) || string.IsNullOrEmpty(user.PW))
                        return false;
                    return true;
                }
                return false;
            }
            return false;
        }

        public void Execute(object parameter)
        {
            Password user = (Password)parameter;
            viewModel.Register(user);
        }
    }
}

这是 Password.cs 代码

    using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Numerics;
using System.Linq;
using System.Threading.Tasks;

namespace ButtonTest.Model
{
    public class Password : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        private string username;
        public string UserName
        {
            get { return username; }
            set
            {
                username = value;
                OnPropertyChanged("UserName");
            }
        }

        private string pw;
        public string PW
        {
            get { return pw; }
            set
            {
                pw = value;
                OnPropertyChanged("PW");
            }
        }

        private string confirmPassword;
        public string ConfirmPassword
        {
            get { return confirmPassword; }
            set
            {
                confirmPassword = value;
                OnPropertyChanged("ConfirmPassword");
            }
        }

        private string email;
        public string Email
        {
            get { return email; }
            set { email = value; }
        }

        public static async void Insert(Password password)
        {
            await App.client.GetTable<Password>().InsertAsync(password);
            //await App.client.SyncContext.PushAsync();

        }
        public static async Task<bool> Delete(Password password)
        {
            try
            {
                await App.passwordsTable.DeleteAsync(password);
                //await App.client.SyncContext.PushAsync();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        public static async void Register(Password user)
        {
            await App.client.GetTable<Password>().InsertAsync(user);
        }
        public static async Task<bool> Login(string username, string password)
        {
            bool isEmailEmpty = string.IsNullOrEmpty(username);
            bool isPasswordEmpty = string.IsNullOrEmpty(password);
            if (isEmailEmpty || isPasswordEmpty)
            {
                return false;
            }
            else
            {
                var user = (await App.client.GetTable<Password>().Where(u => u.UserName == username).ToListAsync()).FirstOrDefault();
                if (user != null)
                {
                    App.user = user;
                    if (user.pw == password)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
        }
    }
}

标签: xamarinbutton

解决方案


这个问题就解决了。RegisterCommand 的 CommandParameter 绑定需要设置为 VM 中的 User 属性。现在,对于 UserName、PW 和 ConfirmPassword 字段中的每次更改都会调用 CanExecute 方法。

它由 github 支持组的 EZ Hart 解决。非常感谢您的解决方案。


推荐阅读