绑定命令不适用于 ReactiveUI 6.5.2 Xamarin whitout XAML

Bind Commands dont work on ReactiveUI 6.5.2 Xamarin whitout XAML

嗨,有人帮我解决这个问题,我不知道为什么会出现这个错误。 我有一个用 C# 和 Xamarin Forms 硬编码的视图,没有 XAML 文件,在这个配置上,我成功地显示了视图,但是当我尝试将命令绑定到 ReactiveUI 6.5.2 时,错误启动了异常,下面你有例外,代码:

UNHANDLED EXCEPTION:

System.Exception: 找不到类型 Xamarin.Forms.Entry 的默认值 属性 在 ReactiveUI.Reflection.getViewExpressionWithProperty(System.Object 视图,System.Linq.Expressions.Expression vmExpression)[0x00059] 在 /Users/paul/code/reactiveui/reactiveui/ReactiveUI/Reflection.cs:259

和代码:

public class EntryPageCode : ReactiveContentPage<APISettingsViewModel>
{

    StackLayout layout;
    public Button SaveUrl { get; protected set; }
    public Entry Url{ get; set; }

    public EntryPageCode()
    {
        layout = new StackLayout { Padding = new Thickness(0, 20, 0, 0) };
        this.Title = "Settings";

        Url = new Entry
        {
            Text = "",//Here the trick
            Placeholder = "API url Please"
        };

        SaveUrl = new Button
        {
            Text = "Save",
            Font = Font.SystemFontOfSize(NamedSize.Large),
            BorderWidth = 1,
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.CenterAndExpand
        };

        Label messagemLbl = new Label
        {
            Text = "Loading",
            Font = Font.BoldSystemFontOfSize(50),
            HorizontalOptions = LayoutOptions.Center
        };

        ActivityIndicator Loading = new ActivityIndicator
        {
            IsRunning = false,
        };

        layout.Children.Add(new Label { Text = "URL" });
        layout.Children.Add(Url);
        layout.Children.Add(SaveUrl);
        layout.Children.Add(messagemLbl);
        layout.Children.Add(Loading);

       this.Content = layout;

        this.Bind(ViewModel, vm => vm.Url, Url.Text);
        this.BindCommand(ViewModel, vm => vm.SaveUrl, v => v.SaveUrl);

        this.WhenAnyValue(x => x.ViewModel.IsLoading)
           .ObserveOn(RxApp.TaskpoolScheduler)
           .Subscribe(busy =>
           {
               Url.IsEnabled = !busy;
               Loading.IsVisible = busy;
               Loading.IsRunning = busy;
           });
    }

}

 public abstract class ReactiveContentPage<TViewModel> : ContentPage, IViewFor<TViewModel> where TViewModel : class
{

    public ReactiveContentPage()
    {
        ViewModel = Activator.CreateInstance<TViewModel>();
        SetupUserInterface();
        SetupReactiveObservables();
    }

    protected readonly CompositeDisposable SubscriptionDisposables = new CompositeDisposable();

    //public static readonly BindableProperty ViewModelProperty =
    //  BindableProperty.Create<ReactiveContentPage<TViewModel>, TViewModel>(x => x.ViewModel, null, BindingMode.OneWay);

    public static readonly BindableProperty ViewModelProperty =
        BindableProperty.Create(nameof(ViewModel), typeof(TViewModel), typeof(ReactiveContentPage<TViewModel>), null, BindingMode.OneWay);

    #region IViewFor implementation
    public TViewModel ViewModel
    {
        get
        {
            return (TViewModel)GetValue(ViewModelProperty);
        }
        set
        {
            SetValue(ViewModelProperty, value);
        }
    }
    #endregion

    #region IViewFor implementation
    object IViewFor.ViewModel
    {
        get
        {
            return ViewModel;
        }
        set
        {
            ViewModel = (TViewModel)value;
        }
    }
    #endregion

    protected virtual void SetupUserInterface() { }

    protected virtual void SetupReactiveObservables() { }

    protected virtual void SetupReactiveSubscriptions() { }

    protected override void OnAppearing()
    {
        SetupReactiveSubscriptions();

        base.OnAppearing();
    }

    protected override void OnDisappearing()
    {
        SubscriptionDisposables.Clear();
        base.OnDisappearing();
    }
}

public class APISettingsViewModel : ReactiveObject
{
    //await Navigation.PopAsync();
    #region Inital Variables
    private string _url;
    private Realm _realm;

    public ReactiveCommand<string> SaveUrl { get; protected set; }

    public string Url
    {
        get { return _url; }
        set { this.RaiseAndSetIfChanged(ref _url, value); }
    }

    readonly ObservableAsPropertyHelper<bool> _isLoading;
    public bool IsLoading
    {
        get { return _isLoading.Value; }
    }
    #endregion

    #region Constructor
    /// <summary>
    /// Constructor View Model
    /// </summary>
    /// <param></param>
    public APISettingsViewModel()
    {

        #region Initialize Varables

        _realm = Realm.GetInstance();

        var config = _realm.All<APISettings>().Where(d => d.Url != null).FirstOrDefault();
        if (config != null)
        {
            _url = config.Url;
        }
        #endregion

        #region Initialize Rx Settings

        var canSave = this.WhenAnyValue(x => x.Url, (ur) =>
        {
            return !String.IsNullOrWhiteSpace(ur) &&
            Regex.IsMatch(ur, @"^(http|https|ftp|)\://|[a-zA-Z0-9\-\.]+\.[a-zA-Z](:[a-zA-Z0-9]*)?/?([a-zA-Z0-9\-\._\?\,\'/\\+&amp;%$#\=~])*[^\.\,\)\(\s]$",
                RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250));
        });

        SaveUrl = ReactiveCommand.CreateAsyncTask<string>(canSave,

            async _ =>
            {
                return await RealmSaveUrl();
            }
            );
        SaveUrl.IsExecuting.ToProperty(this, x => x.IsLoading, out _isLoading);
        SaveUrl.ThrownExceptions
            .Subscribe(ex => UserError.Throw("Error", ex));
        SaveUrl.Subscribe(
                r =>
                {
                    Debug.WriteLine("See it:" + r.ToString());
                }
            );

        #endregion



    }
    #endregion

    #region Methods
    private async Task<string> RealmSaveUrl()
    {

        try
        {
            var apiSet = _realm.All<APISettings>().FirstOrDefault();

            if (apiSet == null)
            {
                _realm.Write(() =>
                {
                    apiSet = _realm.CreateObject<APISettings>();
                    apiSet.Url = Url;
                });
            }
            else
            {
                _realm.Write(() =>
                {
                    apiSet.Url = Url;
                });
            }

            return apiSet.Url;
        }
        catch (Exception ex)
        {
            Debug.WriteLine("Error >> " + ex.StackTrace);
            return "IHandleObservableErrors";
        }


    }

    #endregion


}

我认为这是 Url 绑定的问题。它说找不到类型 Xamarin.Forms.Entry 的默认 属性,这是 Url 的类型。您需要提供它所绑定的 属性,即 Text.

this.Bind(ViewModel, vm => vm.Url, v => v.Url.Text);

您需要在 Entry 实例上推送此行:

Url = new Entry
        {
            Text = "",
            Placeholder = "API url Please"
        };

您需要将初始文本放入此 BindableProperty 作品中,关闭诅咒。 我会编辑代码,由于某些原因其他人以后有同样的问题。