C# 将isEnabled绑定到xaml中的按钮时出错
我不熟悉xaml、WPFs、C#和MVVM范式。我从一个基于的应用程序开始,在所选摘录中,我希望在单击“身份验证”按钮后从LoginPageViewModel禁用“身份验证”按钮(如果您已通过身份验证,则单击该按钮没有意义)。我已经实现了命令绑定,以及视图和ViewModel之间的文本控件绑定。我的LoginPageViewModel基于从INotifyPropertyChanged继承的抽象类 setter AuthenticateButtonEnabled正在工作,但它未绑定到窗体上的isEnabled属性。我的问题是,我可能遗漏了什么,以及如何跟踪视图和视图模型之间的绑定 LoginPageView.xaml按钮:C# 将isEnabled绑定到xaml中的按钮时出错,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,我不熟悉xaml、WPFs、C#和MVVM范式。我从一个基于的应用程序开始,在所选摘录中,我希望在单击“身份验证”按钮后从LoginPageViewModel禁用“身份验证”按钮(如果您已通过身份验证,则单击该按钮没有意义)。我已经实现了命令绑定,以及视图和ViewModel之间的文本控件绑定。我的LoginPageViewModel基于从INotifyPropertyChanged继承的抽象类 setter AuthenticateButtonEnabled正在工作,但它未绑定到窗体上的isE
<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"/>
如果将按钮的command属性绑定到Viewmodel中的ICommand属性,则不需要处理按钮的IsEnabled属性,因为它由ICommand实现的CanExecute方法处理
如果您想同时启用:command和
AuthenticateButtonEnabled
,只需在CanExecute
delegate中检查此属性,在property setter update命令中反之亦然
以下是您可能会发现有用的实施和一些改进:
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
command委托中,当它执行长时间运行的命令时,您可能需要检查答案。).多亏了海报的帮助,我想与其他人分享工作解决方案。我使用了DelegateCommand,但不得不更改loginPageViewModel中的某些部分以使其工作:我还更新了xaml,以便在成功验证后所有控件都处于非活动状态
登录页面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"/>
此外,我还补充说:
public void Update()
{
if (CanExecuteChanged != null)
CanExecuteChanged(this, EventArgs.Empty);
}
Sinatr感谢您的建议,我发现使用这个MVVM范例非常令人沮丧-一个简单的.enabled=false花费了我一天的大部分时间来实现-我忍不住认为这个范例太复杂,无法使用…当然从表示中抽象逻辑是好的,但我忍不住认为它应该更容易。。。。
....
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);
}
public void Update()
{
if (CanExecuteChanged != null)
CanExecuteChanged(this, EventArgs.Empty);
}