MvxTimePicker无法绑定TimeSpan问题求助
嘿,我之前在MvvmCross 6.0的Android项目里也碰到过MvxTimePicker绑定TimeSpan的问题,折腾了好一会儿才搞定,给你两个实用的解决方案:
方案1:使用双向值转换器
MvxTimePicker默认绑定的是Android原生的Time类型,而我们ViewModel里的属性是TimeSpan,所以需要一个双向值转换器来在两者之间做转换。
首先创建转换器类:
public class TimeToTimeSpanConverter : MvxValueConverter<TimeSpan, Time>, IMvxValueConverter { protected override Time Convert(TimeSpan value, Type targetType, object parameter, CultureInfo culture) { var time = new Time(); time.Hour = value.Hours; time.Minute = value.Minutes; time.Second = value.Seconds; return time; } protected override TimeSpan ConvertBack(Time value, Type targetType, object parameter, CultureInfo culture) { if (value == null) return TimeSpan.Zero; return new TimeSpan(value.Hour, value.Minute, value.Second); } }
接下来在布局里引用这个转换器:
<MvxTimePicker android:layout_width="match_parent" android:layout_height="wrap_content" local:MvxBind="Time MyTimeSpanProperty, Converter=TimeToTimeSpan" />
最后别忘了在Setup.cs里注册转换器,让MvvmCross能找到它:
protected override void FillValueConverters(IMvxValueConverterRegistry registry) { base.FillValueConverters(registry); registry.AddOrOverwrite("TimeToTimeSpan", new TimeToTimeSpanConverter()); }
方案2:自定义MvxTimeSpan绑定
如果觉得转换器不够直接,也可以自定义一个专门针对TimeSpan的绑定逻辑,这样布局里的写法会更简洁。
先创建绑定类:
public class MvxTimePickerTimeSpanBinding : MvxAndroidTargetBinding { private readonly MvxTimePicker _timePicker; private IDisposable _subscription; public MvxTimePickerTimeSpanBinding(MvxTimePicker view) : base(view) { _timePicker = view; } public override Type TargetType => typeof(TimeSpan); public override MvxBindingMode DefaultMode => MvxBindingMode.TwoWay; protected override void SetValueImpl(object target, object value) { if (value is TimeSpan timeSpan) { var time = new Time(); time.Hour = timeSpan.Hours; time.Minute = timeSpan.Minutes; time.Second = timeSpan.Seconds; _timePicker.Time = time; } } public override void SubscribeToEvents() { _subscription = _timePicker.TimeChangedObservable.Subscribe(OnTimeChanged); } private void OnTimeChanged(Time time) { var timeSpan = new TimeSpan(time.Hour, time.Minute, time.Second); FireValueChanged(timeSpan); } protected override void Dispose(bool isDisposing) { if (isDisposing) { _subscription?.Dispose(); _subscription = null; } base.Dispose(isDisposing); } }
然后在Setup.cs里注册这个自定义绑定:
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry) { base.FillTargetFactories(registry); registry.RegisterFactory(new MvxCustomBindingFactory<MvxTimePicker>("TimeSpan", view => new MvxTimePickerTimeSpanBinding(view))); }
现在布局里就能直接绑定TimeSpan属性了:
<MvxTimePicker android:layout_width="match_parent" android:layout_height="wrap_content" local:MvxBind="TimeSpan MyTimeSpanProperty" />
额外注意点
- 确保你的ViewModel属性是
public TimeSpan MyTimeSpanProperty { get; set; },并且ViewModel继承自MvxViewModel(它已经实现了INotifyPropertyChanged,能自动通知UI更新)。 - 如果你的TimeSpan可能超过24小时,记得额外处理,因为MvxTimePicker默认只支持0-23小时的范围。
内容的提问来源于stack exchange,提问作者Jim Wilcox
相关产品推荐
相关产品推荐

