Как: создать кнопку переключения XAML - PullRequest
0 голосов
/ 04 декабря 2018

Я хочу переключать привязки текста и команд для кнопки на основе свойства VM.Connected.

По какой-то причине кнопка, кажется, "теряет" свою привязку к команде после второго щелчка.(т. е. Соединить -> Разъединить -> Соединить -> Не вызывает -> VM.Connect)

Кроме того, ActivityIndicatordoes не отображается и не запускается, когда IsBusy имеет значение true;

Просмотр XAML

    <Button>
        <Button.Style>
            <Style TargetType="Button">
                <Style.Triggers>
                    <DataTrigger TargetType="Button" Binding="{Binding Connected}" Value="False">
                        <Setter Property="Text" Value="Connect"/>
                        <Setter Property="Command" Value="{Binding Connect}"/>
                    </DataTrigger>
                    <DataTrigger TargetType="Button" Binding="{Binding Connected}" Value="True">
                        <Setter Property="Text" Value="Disconnect"/>
                        <Setter Property="Command" Value="{Binding Disconnect}"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Button.Style>
    </Button>

    <ActivityIndicator IsVisible="{Binding IsBusy}" IsRunning="{Binding IsBusy}" Color="DarkBlue"/> 

Просмотр модели

protected INavigationService NavigationService { get; private set; }

    protected ICommunicationService CommunicationService;        

    private ObservableAsPropertyHelper<bool> _isBusy;
    public bool IsBusy => _isBusy.Value;

    private ObservableAsPropertyHelper<bool> _connected;        
    public bool Connected => _connected.Value;

    public ReactiveCommand<Unit, bool> Connect { get; }
    public ReactiveCommand<Unit, bool> Disconnect { get; }

    public MainPageViewModel(INavigationService navigationService, ICommunicationService communicationService)
    {
        CommunicationService = communicationService;
        NavigationService = navigationService;

        _isBusy = this
            .WhenAnyObservable(x => x.Connect.IsExecuting)
            .ObserveOn(RxApp.MainThreadScheduler)
            .ToProperty(this, x => x.IsBusy, false);                            

        _connected = this
            .WhenAnyValue(x => x.CommunicationService.Connected)
            .ObserveOn(RxApp.MainThreadScheduler)
            .ToProperty(this, x => x.Connected, false);

        Connect = ReactiveCommand.CreateFromTask(
            CommunicationService.ConnectAsync, 
            this.WhenAnyValue(
                x => x.IsBusy, y => y.Connected, 
                (isBusy, isConnected) => CanConnect(isBusy,isConnected))
                .ObserveOn(RxApp.MainThreadScheduler));

        Disconnect = ReactiveCommand.CreateFromTask(
            CommunicationService.DisconnectAsync, 
            this.WhenAnyValue(
                x => x.IsBusy, y => y.Connected, 
                (isBusy, isConnected) => CanDisonnect(isBusy, isConnected))
                .ObserveOn(RxApp.MainThreadScheduler));            

    }

    private bool CanConnect(bool isBusy, bool isConnected)
    {
        return !isBusy && !isConnected;
    }

    private bool CanDisonnect(bool isBusy, bool isConnected)
    {
        return !isBusy && isConnected;
    }

Сервисная модель

public interface ICommunicationService
{
    bool Connected { get; }
    Task<bool> ConnectAsync();                
    Task<bool> DisconnectAsync();
}
public class CommunicationService : ReactiveObject, ICommunicationService
{
    private bool _connected;
    public bool Connected { get => _connected; private set => this.RaiseAndSetIfChanged(ref _connected, value); }

    public async Task<bool> ConnectAsync()
    {
        await Task.Delay(1000);
        Connected = true;
        return Connected;
    }

    public async Task<bool> DisconnectAsync()
    {
        await Task.Delay(1000);
        Connected = false;
        return Connected;            
    }      
}
...