【问题标题】:Bind Commands dont work on ReactiveUI 6.5.2 Xamarin whitout XAML绑定命令在没有 XAML 的 ReactiveUI 6.5.2 Xamarin 上不起作用
【发布时间】:2016-11-01 21:19:30
【问题描述】:

嗨,有人帮我解决这个问题,我不知道为什么会出现这个错误。 我有一个在没有 XAML 文件的 C# 和 Xamarin Forms 中硬编码的视图,在这个配置上,我成功地显示了视图,但是当我尝试将命令绑定到 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


}

【问题讨论】:

    标签: c# xamarin xamarin.forms reactive-programming reactiveui


    【解决方案1】:

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

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

    你需要把初始文本,这个 BindableProperty 工程,关闭诅咒。 我将编辑代码,由于某些原因,其他人将来也会遇到同样的问题。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 同样的错误仍然存​​在,我编辑了问题的代码,谢谢你的尝试。
      猜你喜欢
      • 1970-01-01
      • 2017-08-18
      • 2020-03-06
      • 2019-12-13
      • 1970-01-01
      • 2017-07-22
      • 2014-09-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多