我有一个使用 MvvmCross 6.0 的安卓应用。我正在尝试将 MvxTimePicker 绑定(bind)到 TimeSpan。我的布局是:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/TableHeaderTextView"
android:text="Start Time"/>
<MvxTimePicker
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:timePickerMode="spinner"
android:textSize="20dp"
local:MvxBind="Value StoreOpens" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Close"
local:MvxBind="Click CloseCommand" />
</LinearLayout>
我的 ViewModel 是:
public class StoreOpenDialogViewModel : MvxViewModel<Site, bool>
{
private readonly IMvxNavigationService _navigationService;
public StoreOpenDialogViewModel(IMvxNavigationService navigationService)
{
_navigationService = navigationService;
CloseCommand = new MvxAsyncCommand(async () => await _navigationService.Close(this, true));
}
public override System.Threading.Tasks.Task Initialize()
{
return base.Initialize();
}
public override void Prepare(Site parm)
{
base.Prepare();
this.Site = parm;
}
public IMvxAsyncCommand CloseCommand { get; private set; }
private Site _Site;
public Site Site
{
get
{
return _Site;
}
set
{
_Site = value;
RaisePropertyChanged(() => Site);
RaisePropertyChanged(() => StoreOpens);
}
}
public TimeSpan StoreOpens
{
get
{
if (Site == null || Site.Opens == null)
return new TimeSpan(8, 0, 0);
else
return Site.Opens;
}
set
{
if (Site != null)
{
Site.Opens = value;
RaisePropertyChanged(() => StoreOpens);
}
}
}
}
我的观点是:
[MvxDialogFragmentPresentation]
[Register(nameof(StoreOpenDialogView))]
public class StoreOpenDialogView : MvxDialogFragment<StoreOpenDialogViewModel>
{
public StoreOpenDialogView()
{
}
protected StoreOpenDialogView(IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
{
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var ignore = base.OnCreateView(inflater, container, savedInstanceState);
var view = this.BindingInflate(Resource.Layout.StoreOpenDialogView, null);
return view;
}
}
这应该是一个非常普通的实现。 Site.Opens 是一个 TimeSpan。当我打开对话框时,出现以下错误:
[ERROR] (MvxBind) Problem seen during binding execution for binding Value for StoreOpens - problem TargetInvocationException: Exception has been thrown by the target of an invocation.
对话框出现并显示当前时间。当我尝试更改时间时,我得到:
04-29 21:26:55.562 I/mono-stdout(20515): java.lang.NoSuchMethodError: no non-static method "Landroid/widget/TimePicker;.getHour()I" at mvvmcross.platforms.android.binding.views.MvxLayoutInflater.n_onCreateView(Native Method)04-29 21:26:55.562 I/mono-stdout(20515): at mvvmcross.platforms.android.binding.views.MvxLayoutInflater.n_onCreateView(Native Method)
我从另一个仍在运行 MvvmCross 5.x 的项目中复制了它,它正在运行。我不知道我是否错过了一步,或者 6.0 中是否出现了问题。有人对此有任何想法吗?
谢谢, 吉姆
最佳答案
从 API 23 开始,Android TimePicker 的属性似乎已更改名称。MvxTimePicker 绑定(bind)到仅存在于 API 23 和更新版本上的 Hour。我的解决方法如下。我将 MvxTimePicker 更改为 TimePicker,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/TableHeaderTextView"
android:text="Start Time" />
<TimePicker
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:timePickerMode="spinner"
android:id="@+id/tpTime"
android:textSize="20dp" />
<!--local:MvxBind="Value StartTime" />-->
<LinearLayout
android:orientation="horizontal"
android:gravity="right"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Close"
style="@style/DialogButton"
local:MvxBind="Click CloseCommand" />
</LinearLayout>
</LinearLayout>
我将 MvxDialogFragment 中的 OnCreateView 更改为:
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var ignore = base.OnCreateView(inflater, container, savedInstanceState);
var view = this.BindingInflate(Resource.Layout.HoursStartDialogView, null);
var tp = view.FindViewById<TimePicker>(Resource.Id.tpTime);
if (Build.VERSION.SdkInt <= BuildVersionCodes.LollipopMr1)
{
#pragma warning disable CS0618
tp.CurrentHour = (Java.Lang.Integer)ViewModel.StartTime.Hours;
tp.CurrentMinute = (Java.Lang.Integer)ViewModel.StartTime.Minutes;
}
else
{
tp.Hour = ViewModel.StartTime.Hours;
tp.Minute = ViewModel.StartTime.Minutes;
}
tp.TimeChanged += (s, e) =>
{
ViewModel.StartTime = new TimeSpan(e.HourOfDay, e.Minute, 0);
};
return view;
}
是的,这与我原来的问题来自不同的应用程序,但我首先修复了这个,因此一些名称发生了变化。这适用于早期版本的 Android。
我将在 MvvmCross 网站上提出错误建议,但这暂时可以解决问题。
**** 更新 ****
此错误将在 MvvmCross 版本 6.0.2 中修复,我的原始帖子将按预期运行。
关于android - MvxTimePicker 不会绑定(bind)到 TimeSpan,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50093069/