WPF ReactiveUI ReactiveCommand对行动做出如此长的反应

时间:2018-06-11 12:34:35

标签: c# wpf reactiveui

我已经堆叠了ReactiveUI命令。 这一切都很好,但ui界面反应太慢了。为什么???? enter image description here 此图显示了从用户单击操作到ReactiveCommand.IsExecuting = True

的时间
    public class LoginWindowViewModel: ReactiveObject, ISupportsActivation
{
    public ReactiveCommand<PasswordBox, Models.User> LoginCommand { get; }
    public ReactiveCommand<Unit, Unit> CancelLoginCommand { get; }

    bool _isErrorShown;
    public bool IsErrorShown
    {
        get { return _isErrorShown; }
        set { this.RaiseAndSetIfChanged(ref _isErrorShown, value); }
    }

    string _login;
    public string Login { get { return _login; } set { this.RaiseAndSetIfChanged(ref _login, value); } }
    ObservableAsPropertyHelper<bool> _isExecuting;
    public bool IsExecuting { get { return _isExecuting.Value; } }

    public ViewModelActivator Activator => new ViewModelActivator();

    public LoginWindowViewModel(Services.AuthService service)
    {
        LoginCommand = ReactiveCommand.CreateFromObservable(
            (PasswordBox passwordField) => Observable.StartAsync(ct => {
                IsErrorShown = false;
                return service.AuthBasicAsync(Login, passwordField.Password, ct);
            }, RxApp.MainThreadScheduler).TakeUntil(CancelLoginCommand),
            this.WhenAnyValue(vm => vm.Login).Select(q => !string.IsNullOrEmpty(q)));
        CancelLoginCommand = ReactiveCommand.Create(() => { });

        _isExecuting = LoginCommand.IsExecuting.ToProperty(this, x => x.IsExecuting, false);
        LoginCommand.ThrownExceptions.Subscribe((obj) =>
        {
            if (obj is UnauthorizedAccessException)
            {
                IsErrorShown = true;
            } else
            {
                throw obj;
            }
        });
    }
}

按钮的绑定是<Button Content="{local:Gettext Login}" Width="75" Margin="5" x:Name="LoginButton" Command="{Binding LoginCommand}" CommandParameter="{Binding ElementName=PasswordField}" IsDefault="True" Click="CancelButton_Click" />

服务:         公共类AuthService         {             受保护的字符串NtlmAuthUrl;             protected string BasicAuthUrl;             public AuthService(string basicAuthUrl,string ntlmAuthUrl)             {                 BasicAuthUrl = basicAuthUrl;                 NtlmAuthUrl = ntlmAuthUrl;             }

        public static RestRequest MakeHandshakedRequest(string url)
        {
            var req = new RestRequest(url, Method.POST);
            req.AddParameter("platform", Environment.OSVersion.ToString());
            req.AddParameter("hash", DeviceIdService.GetDeviceId());
            req.AddParameter("type", "Desktop");
            req.AddParameter("name", Environment.MachineName);
            req.AddParameter("app_version", Assembly.GetAssembly(typeof(App)).GetName().Version.ToString());
            req.AddParameter("locale", Thread.CurrentThread.CurrentCulture.Name);
            req.AddParameter("ntlm_auth_supported", App.Current.DataSource.UseNtlmAuth);
            req.AddParameter("encoding", "utf-8");

            return req;
        }

        protected Models.User ValidateResponse(IRestResponse<Models.User> user_response)
        {

            if (user_response.StatusCode == HttpStatusCode.Unauthorized)
            {
                throw new UnauthorizedAccessException();
            }

            if (user_response.ErrorException != null)
            {
                throw user_response.ErrorException;
            }

            if (!user_response.IsSuccessful)
            {
                throw new InvalidDataSourceException();
            }
            return user_response.Data;
        }

        protected async Task<Models.User> ExecuteAuthAsync(string url, RestClient client, CancellationToken token)
        {

            var req = MakeHandshakedRequest(url);

            var user_response = await client.ExecuteTaskAsync<Models.User>(req, token);

            return ValidateResponse(user_response);
        }

        public Task<Models.User> AuthBasicAsync(string login, string password, CancellationToken token)
        {
            var client = new RestClient(App.Current.DataSource.BaseUrl)
            {
                Authenticator = new HttpBasicAuthenticator(login, password),
                Encoding = Encoding.UTF8,
            };

            return ExecuteAuthAsync(BasicAuthUrl, client, token);
        }
    }
}

查看:

    public partial class LoginWindow : Window, IViewFor<LoginWindowViewModel>
    {
        public Models.User User { get; protected set; }
        private DateTime dt_start;
        public LoginWindow(Services.AuthService service)
        {
            ViewModel = new LoginWindowViewModel(service);
            InitializeComponent();
            DataContext = ViewModel;
            ViewModel.LoginCommand.Subscribe((user) =>
            {
                User = user;
                DialogResult = true;
                Close();
            });

            ViewModel.CancelLoginCommand.Subscribe(_ =>
            {
                Close();
            });
            ViewModel.LoginCommand.IsExecuting.Subscribe(_ =>
            {
                MessageBox.Show("Time elapsed from click to command executing is: " + (DateTime.Now - dt_start));
            });
        }

        public LoginWindowViewModel ViewModel { get; set; }
        object IViewFor.ViewModel { get => ViewModel; set => ViewModel = value as LoginWindowViewModel; }

        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
            dt_start = DateTime.Now;
        }
    }
}

0 个答案:

没有答案