绑定命令不适用于 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\-\._\?\,\'/\\+&%$#\=~])*[^\.\,\)\(\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 作品中,关闭诅咒。
我会编辑代码,由于某些原因其他人以后有同样的问题。
嗨,有人帮我解决这个问题,我不知道为什么会出现这个错误。 我有一个用 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\-\._\?\,\'/\\+&%$#\=~])*[^\.\,\)\(\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 作品中,关闭诅咒。 我会编辑代码,由于某些原因其他人以后有同样的问题。