首页 文章

错误绑定isEnabled到xaml中的按钮

提问于
浏览
2

我是xaml,WPF,C#和MVVM范例的新手 . 我已经开始使用基于this example project的应用程序,在选定的摘录中,我想在单击身份验证按钮后从LoginPageViewModel中禁用身份验证按钮(如果您通过身份验证,则无需点击该按钮) . 我有命令绑定工作,以及视图和ViewModel之间的文本控制绑定 . 我的LoginPageViewModel基于一个继承自INotifyPropertyChanged的抽象类

setter AuthenticateButtonEnabled正在工作,但它没有绑定到表单上的isEnabled proprerty . 我的问题是,我可以错过什么,以及如何跟踪View和ViewModel之间的绑定?

LoginPageView.xaml按钮:

<Button x:Name="authenticateButton" Content="{x:Static res:Strings.LoginPage_authenticateButton_content}" 
            Grid.Column="2" Margin="53,4,0,10" 
            Grid.Row="2" FontSize="16" 
            IsEnabled="{Binding Path=AuthenticateButtonEnabled}"
            Command="{Binding Path=AuthenticateCommand}" HorizontalAlignment="Left" Width="87"/>

viewModel

private String _username;
    private String _responseTextBlock;
    private String _linkTextBlockURI;
    private String _linkTextBlockText;
    private bool _authenticateButtonEnabled;
    ...
    private async void Authenticate()
    {
        ResponseTextBlock = Strings.LoginPage_responseBlock_content_checking;#this works!
        AuthenticateButtonEnabled = false;
        return;

    }
    ....

    public bool AuthenticateButtonEnabled 
    {
        get { return _authenticateButtonEnabled; }
        set { _authenticateButtonEnabled = value;  OnPropertyChanged("AuthenticateButtonEnabled"); }
    }
    // this is in the abstract class.
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }

3 回答

  • 1

    如果要同时具有:command和 AuthenticateButtonEnabled ,则只需在 CanExecute 委托中检查此属性,然后在property setter update命令中检查vise-versa .

    以下是DelegateCommand的实现以及一些您可能会觉得有用的改进:

    bool _isAuthenticateButtonEnabled;
    public bool IsAuthenticateButtonEnabled 
    {
        get { return _isAuthenticateButtonEnabled; }
        set
        {
            _isAuthenticateButtonEnabled = value;
            OnPropertyChanged();
            AuthenticateCommand.Update();
        }
    }
    
    // the base could class could actually implement this
    void OnPropertyChanged([CallerMemberName] string property) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
    
    public DelegateCommand AuthenticateCommand { get; }
    
    // view model constructor
    public ViewModel()
    {
        AuthenticateCommand = new DelegateCommand(o =>
        {
           ... // some actions when command is executed
        }, o =>
        {
           bool somecondition = ...; // some condition to disable button, e.q. when executing command
           return somecondition && IsAuthenticateButtonEnabled;
        });
    }
    

    这将允许您同时具有:属性启用/禁用按钮,可用于绑定(到另一个控件,例如 CheckBox.IsChecked )和可以具有独立条件的命令,以便在不应执行命令时禁用按钮(通常在 async 中命令委托,当它执行长时间运行的命令时,但为此你可能想检查this的答案 . ) .

  • 0

    如果将Button的命令属性绑定到Viewmodel中的ICommand属性,则不需要处理Button的IsEnabled属性,因为它由ICommand实现的CanExecute方法处理 .

    google for RelayCommand或DelegateCommand

  • 1

    感谢海报的帮助,我想为其他人分享工作解决方案 . 我使用了DelegateCommand,但不得不更改loginPageViewModel中的一些部分以使其工作:我还更新了xaml,以便在成功验证后控件都处于非活动状态 .

    loginPage xaml:

    <Label x:Name="usernameLabel"  Content="{x:Static res:Strings.LoginPage_usernameLabel_content}" HorizontalAlignment="Left" Margin="10,4,0,0" Grid.Row="0" VerticalAlignment="Top" Width="130" FontSize="16"  Height="36" Grid.Column="1"/>
        <TextBox x:Name="usernameTextBox" Grid.Column="2" Grid.Row="0" TextWrapping="Wrap" 
                 Text="{Binding Username, UpdateSourceTrigger=PropertyChanged}" 
                 IsEnabled="{Binding AuthenticateButtonEnabled}"
                 Margin="10,5,0,6" FontSize="16" HorizontalAlignment="Left" Width="130" TextChanged="usernameTextBox_TextChanged"/>
        <Label x:Name="passwordLabel" Content="{x:Static res:Strings.LoginPage_passwordLabel_content}" Margin="10,5,0,0" Grid.Row="1" VerticalAlignment="Top" FontSize="16" Height="36" Grid.RowSpan="2" HorizontalAlignment="Left" Width="130" Grid.Column="1"/>
        <PasswordBox x:Name="passwordBox" Grid.Column="2" Margin="10,0,0,9" 
            PasswordChanged="PasswordBox_PasswordChanged"
            IsEnabled="{Binding AuthenticateButtonEnabled}"
            Grid.Row="1" FontSize="16" HorizontalAlignment="Left" Width="130"/>
        <Button x:Name="authenticateButton" Content="{x:Static res:Strings.LoginPage_authenticateButton_content}" 
                Grid.Column="2" Margin="53,4,0,10" 
                Grid.Row="2" FontSize="16" 
                IsEnabled="{Binding AuthenticateButtonEnabled}"
                Command="{Binding Path=AuthenticateCommand}" HorizontalAlignment="Left" Width="87"/>
    

    loginPageViewModel:

    ....
        private bool _authenticateButtonEnabled;
        private DelegateCommand _authenticateCommand;
        public bool AuthenticateButtonEnabled {
            get { return _authenticateButtonEnabled; }
            set
            {
                _authenticateButtonEnabled = value;
                DynamicOnPropertyChanged(); // this is so named to not content with onPropertyChanged defined elsewhere.
                AuthenticateCommand.Update();
            }
        }
        ...
    
        public DelegateCommand AuthenticateCommand
        { 
            get {
                if (_authenticateCommand == null)
                {
                    _authenticateCommand = new DelegateCommand(Authenticate, AuthenticateEnded);
                }
                return _authenticateCommand;
            }
        }
        private bool AuthenticateEnded(object obj) {
            return _authenticateButtonEnabled;
        }
        private async void Authenticate(object obj)
        {
            AuthenticateButtonEnabled = false;
    
            ResponseTextBlock = Strings.LoginPage_responseBlock_content_checking;
            i3SoftHttpClient _httpClient = new i3SoftHttpClient();
            i3SoftUser _i3SoftUser;
            AuthenticateCommand.CanExecute(false);
            ....
          // if authentication does not succeed - turn the buttons back on.
            AuthenticateCommand.CanExecute(true);
         }
    

    并且_1111011_我补充说:

    public void Update()
        {
            if (CanExecuteChanged != null)
                CanExecuteChanged(this, EventArgs.Empty);
        }
    

相关问题