将条目TextChanged绑定到Xamarin.Forms中按钮命令的CanExecute方法

时间:2017-11-06 06:55:58

标签: c# xamarin mvvm xamarin.forms

如果三个条目中的任何一个为空,我想禁用发送按钮,但是如何以MVVM方式实现?

我想到了CanExecute委托,但是每当TextChanged被解雇时我怎么能解它呢?

此外,如果我选择行为,如果我使用Behavior<Entry>

,如何与其他控件(如按钮)进行通信

这是观点:

<ContentPage.Content>
    <AbsoluteLayout>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="56"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="30"/>
                <RowDefinition Height="10"/>
                <RowDefinition Height="30"/>
                <RowDefinition Height="30"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="50"/>
            </Grid.RowDefinitions>
            <Label Text="Contact Us" FontSize="Medium" Grid.ColumnSpan="3"/>
            <Entry Text="{Binding ContactData.message_name}" x:Name="subject" Grid.Row="2" Grid.Column="1" Placeholder="Subject"/>
            <Entry Keyboard="Email" Text="{Binding ContactData.receiver_email}" x:Name="email" Grid.Row="3" Grid.Column="1" Placeholder="Email"/>
            <Editor Text="{Binding ContactData.message_subject}" x:Name="body" Grid.Row="4" Grid.Column="1" />

            <Button Grid.Row="5" Grid.Column="1" Command="{Binding ContactFormSent}" Text="Send"/>
        </Grid>
    </AbsoluteLayout>
</ContentPage.Content>

ViewModel中的

public ContactViewModel()
{
    ContactFormSent = new RelayCommand(SendContactInfo);
    ContactData = new ContactModel();
}

private bool CanSend() //this only get called when the view model is constructed
{
    return !(string.IsNullOrWhiteSpace(ContactData.receiver_email) && string.IsNullOrWhiteSpace(ContactData.message_subject) &&
        string.IsNullOrWhiteSpace(ContactData.message_name));
}

在“行为”选项中,我希望它与EntryEditor一起使用,那么我的方法是Behavior类,而不是通用版本?如果是的话,我该如何实施呢?

2 个答案:

答案 0 :(得分:1)

Command有一个公开方法ChangeCanExecute()。 当您新增Command时,您可以指定canExecute条件。触发TextChanged事件后,请调用ChangeCanExecute()方法。

示例:

Command someCommand = new Command(
 () => SomeMethod(),
 ()=> { return CanSend(); }
);

Button更改文字后:

private void TextChanged(object sender, TextChangedEventArgs e)
{
    ViewModel.someCommand.ChangeCanExecute();
}

答案 1 :(得分:1)

通常,为了使用MVVM模式对视图事件做出反应,建议您使用EventToCommandBehaviour

但是在这种情况下不需要它,因为绑定到Entry的属性上的setter应该在每次文本更改时触发。您可以使用它来触发ChangeCanExecute()命令,以通知视图现在可以启用/禁用该按钮。

例如:

string _firstName;
public string FirstName
{
    get { return _firstName; }
    set
    {
        if (_firstName != value)
            SendCommand.ChangeCanExecute();
        SetProperty(ref _firstName, value, nameof(FirstName));
    }
}

string _lastName;
public string LastName
{
    get { return _lastName; }
    set
    {
        if (_lastName != value)
            SendCommand.ChangeCanExecute();
        SetProperty(ref _lastName, value, nameof(LastName));
    }
}

string _email;
public string Email
{
    get { return _email; }
    set
    {
        if (_email != value)
            SendCommand.ChangeCanExecute();
        SetProperty(ref _email, value, nameof(Email));
    }
}

Command _sendCommand;
public Command SendCommand 
{
    get
    {
        return _sendCommand ?? (_sendCommand = new Command(OnSend, CanSend));
    }    
}

bool CanSend(object obj)
{
    return Validate();
}

void OnSend(object obj)
{
    if(Validate())
    {
        //actual button click execution
    }
}

bool Validate()
{
    // disable button if any entry empty
    return !string.IsNullOrEmpty(_firstName)
                  && !string.IsNullOrEmpty(_lastName)
                  && !string.IsNullOrEmpty(_email);
}