如何使用 MvvmCross 为 Seekbar 设置 Start/StopTrackingTouch 的绑定
How to set bindings for Start/StopTrackingTouch for Seekbar using MvvmCross
我得到了一种典型的音乐播放器 window,音乐播放时搜索栏点在移动。
我已经使用默认 mvvmcross
绑定到 属性(通过 EventHandler
绑定更改),如下所示:
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/playprogress"
local:MvxBind="Progress ValueOfTimer"
/>
所以现在我希望用户能够前后移动它。
我一直在尝试这样绑定它:
public class PlayWindowView : MvxActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
var set = this.CreateBindingSet<PlayWindowView, PlayWindowViewModel>();
SeekBar seek = FindViewById<SeekBar>(Resource.Id.playprogress);
set.Bind(seek).For("Max").To(viewModel => viewModel.MaxTimerValue);
set.Bind(seek).For("StopTrackingTouch").To(viewModel => viewModel.PlayProgressChanged);
set.Apply();
}
protected override void OnViewModelSet()
{
SetContentView(Resource.Layout.playwindow_view);
}
}
视图模型部分如下所示:
public class PlayWindowViewModel : MvxViewModel<ListMenuItemDto>
{
private long _valueOfTimer;
public long ValueOfTimer
{
get { return _valueOfTimer; }
set
{
_valueOfTimer = value;
RaisePropertyChanged(() => ValueOfTimer);
}
}
//...
public MvxAsyncCommand<long> PlayProgressChanged
{
get { return new MvxAsyncCommand<long>(OnPlayProgressChange);}
}
private async Task OnPlayProgressChange(long progr)
{
await _playingService.SetTime((int) progr).ConfigureAwait(false);
}
}
但看起来它不起作用。
我的意思是,它甚至没有进入 OnPlayProgressChange
。但在视图中出现它进入命令 PlayProgressChanged
一次。
如何将此事件(以及 StartTrackingTouch
、StopTrackingTouch
等事件)正确绑定到函数?
P.S。
仅供参考,我使用 MvvmCross 5
UPD 28.11.2017
尝试了自定义绑定,甚至 Progress
绑定现在都停止工作了。
所以,xaml 现在看起来像这样:
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/playprogress"
local:MvxBind="Progress ValueOfTimer, OnStopTrackingTouch PlayProgressChanged"
/>
活页夹代码在这里
public class SeekbarStopTrackingTouchEventBinding: MvxAndroidTargetBinding
{
private readonly SeekBar _seekbar;
private IMvxAsyncCommand _command;
public SeekbarStopTrackingTouchEventBinding(SeekBar seekbar) : base(seekbar)
{
_seekbar = seekbar;
_seekbar.StopTrackingTouch += ViewOnStopTrackingTouch;
}
private void ViewOnStopTrackingTouch(object sender, SeekBar.StopTrackingTouchEventArgs e)
{
if (_command != null)
{
_command.Execute(e);
}
}
public override Type TargetType
{
get { return typeof (IMvxAsyncCommand); }
}
protected override void SetValueImpl(object target, object value)
{
_command = (IMvxAsyncCommand)value;
}
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
_seekbar.StopTrackingTouch -= ViewOnStopTrackingTouch;
}
base.Dispose(isDisposing);
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.OneWay; }
}
}
}
在设置中:
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
base.FillTargetFactories(registry);
registry.RegisterFactory(new MvxCustomBindingFactory<SeekBar>("OnStopTrackingTouch", (seekbar) => new SeekbarStopTrackingTouchEventBinding(seekbar)));
}
UPD2
更改绑定如下:local:MvxBind="Progress ValueOfTimer; OnStopTrackingTouch PlayProgressChanged"
(注意 ;
此处)并且事件现在触发,是的!
但现在的问题是 - 在 binder
_command
中即使在 SetValueImpl
被解雇并且 _command = (IMvxAsyncCommand)value;
没问题后仍保持空值,value
指向已设置ViewModel 属性.
怎么会?
UPD3
发现无法将 object
转换为 IMvxAsyncCommand
。
我通过更改解决了这个问题
IMvxAsyncCommand _command
到 IMvxAsyncCommand<SeekBar.StopTrackingTouchEventArgs> _command
;
将在答案中总结所有内容。
但现在我有一个问题 - 在这种情况下最好的做法是什么?
所以,我不知道这是不是一个好方法,但目前它的工作,我很高兴。
希望这对像我这样的人有所帮助。
自定义绑定 方法是这里的关键。真正有用的东西在这里:
In MvvmCross how do I do custom bind properties
MVVMCross Bindings in Android
所以,就我而言,为了让应用程序监听 SeekBar
OnStopTrackingTouch
事件,我这样做了:
已创建绑定 class:
public class SeekbarStopTrackingTouchEventBinding: MvxAndroidTargetBinding
{
private readonly SeekBar _seekbar;
private IMvxAsyncCommand<SeekBar.StopTrackingTouchEventArgs> _command;
private string testString;
public SeekbarStopTrackingTouchEventBinding(SeekBar seekbar) : base(seekbar)
{
_seekbar = seekbar;
_seekbar.StopTrackingTouch += ViewOnStopTrackingTouch;
}
private void ViewOnStopTrackingTouch(object sender, SeekBar.StopTrackingTouchEventArgs e)
{
if (_command != null)
{
_command.Execute(e);
}
}
public override Type TargetType
{
get { return typeof (IMvxAsyncCommand); }
}
protected override void SetValueImpl(object target, object value)
{
try
{
_command = (IMvxAsyncCommand<SeekBar.StopTrackingTouchEventArgs>)value;
}
catch (Exception e)
{
Log.Error("SOME BINDER FAIL\n\t" + e.Message + "\n", "SOME BINDER FAIL\n\t" + e.Message + "\n");
throw;
}
}
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
_seekbar.StopTrackingTouch -= ViewOnStopTrackingTouch;
}
base.Dispose(isDisposing);
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.OneWay; }
}
}
在 Setup.cs
中放置此代码:
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
base.FillTargetFactories(registry);
registry.RegisterFactory(new MvxCustomBindingFactory<SeekBar>("OnStopTrackingTouch", (seekbar) => new SeekbarStopTrackingTouchEventBinding(seekbar)));
}
在我的 ViewModel
和命令执行函数中准备 属性:
public IMvxAsyncCommand<SeekBar.StopTrackingTouchEventArgs> PlayProgressChanged
{
get
{
return new MvxAsyncCommand<SeekBar.StopTrackingTouchEventArgs>(OnPlayProgressChange);
}
}
private async Task OnPlayProgressChange(SeekBar.StopTrackingTouchEventArgs e)
{
var progr = e.SeekBar.Progress;
await _playingService.SetTime((int) progr).ConfigureAwait(false);
}
在视图布局中,在 local:MvxBind
内将我的 ViewModel
命令与 Setup.cs
中的 registry.RegisterFactory
中提供的事件名称相关联
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/playprogress"
local:MvxBind="Progress ValueOfTimer; OnStopTrackingTouch PlayProgressChanged"
/>
我得到了一种典型的音乐播放器 window,音乐播放时搜索栏点在移动。
我已经使用默认 mvvmcross
绑定到 属性(通过 EventHandler
绑定更改),如下所示:
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/playprogress"
local:MvxBind="Progress ValueOfTimer"
/>
所以现在我希望用户能够前后移动它。
我一直在尝试这样绑定它:
public class PlayWindowView : MvxActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
var set = this.CreateBindingSet<PlayWindowView, PlayWindowViewModel>();
SeekBar seek = FindViewById<SeekBar>(Resource.Id.playprogress);
set.Bind(seek).For("Max").To(viewModel => viewModel.MaxTimerValue);
set.Bind(seek).For("StopTrackingTouch").To(viewModel => viewModel.PlayProgressChanged);
set.Apply();
}
protected override void OnViewModelSet()
{
SetContentView(Resource.Layout.playwindow_view);
}
}
视图模型部分如下所示:
public class PlayWindowViewModel : MvxViewModel<ListMenuItemDto>
{
private long _valueOfTimer;
public long ValueOfTimer
{
get { return _valueOfTimer; }
set
{
_valueOfTimer = value;
RaisePropertyChanged(() => ValueOfTimer);
}
}
//...
public MvxAsyncCommand<long> PlayProgressChanged
{
get { return new MvxAsyncCommand<long>(OnPlayProgressChange);}
}
private async Task OnPlayProgressChange(long progr)
{
await _playingService.SetTime((int) progr).ConfigureAwait(false);
}
}
但看起来它不起作用。
我的意思是,它甚至没有进入 OnPlayProgressChange
。但在视图中出现它进入命令 PlayProgressChanged
一次。
如何将此事件(以及 StartTrackingTouch
、StopTrackingTouch
等事件)正确绑定到函数?
P.S。 仅供参考,我使用 MvvmCross 5
UPD 28.11.2017
尝试了自定义绑定,甚至 Progress
绑定现在都停止工作了。
所以,xaml 现在看起来像这样:
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/playprogress"
local:MvxBind="Progress ValueOfTimer, OnStopTrackingTouch PlayProgressChanged"
/>
活页夹代码在这里
public class SeekbarStopTrackingTouchEventBinding: MvxAndroidTargetBinding
{
private readonly SeekBar _seekbar;
private IMvxAsyncCommand _command;
public SeekbarStopTrackingTouchEventBinding(SeekBar seekbar) : base(seekbar)
{
_seekbar = seekbar;
_seekbar.StopTrackingTouch += ViewOnStopTrackingTouch;
}
private void ViewOnStopTrackingTouch(object sender, SeekBar.StopTrackingTouchEventArgs e)
{
if (_command != null)
{
_command.Execute(e);
}
}
public override Type TargetType
{
get { return typeof (IMvxAsyncCommand); }
}
protected override void SetValueImpl(object target, object value)
{
_command = (IMvxAsyncCommand)value;
}
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
_seekbar.StopTrackingTouch -= ViewOnStopTrackingTouch;
}
base.Dispose(isDisposing);
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.OneWay; }
}
}
}
在设置中:
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
base.FillTargetFactories(registry);
registry.RegisterFactory(new MvxCustomBindingFactory<SeekBar>("OnStopTrackingTouch", (seekbar) => new SeekbarStopTrackingTouchEventBinding(seekbar)));
}
UPD2
更改绑定如下:local:MvxBind="Progress ValueOfTimer; OnStopTrackingTouch PlayProgressChanged"
(注意 ;
此处)并且事件现在触发,是的!
但现在的问题是 - 在 binder
_command
中即使在 SetValueImpl
被解雇并且 _command = (IMvxAsyncCommand)value;
没问题后仍保持空值,value
指向已设置ViewModel 属性.
怎么会?
UPD3
发现无法将 object
转换为 IMvxAsyncCommand
。
我通过更改解决了这个问题
IMvxAsyncCommand _command
到 IMvxAsyncCommand<SeekBar.StopTrackingTouchEventArgs> _command
;
将在答案中总结所有内容。
但现在我有一个问题 - 在这种情况下最好的做法是什么?
所以,我不知道这是不是一个好方法,但目前它的工作,我很高兴。
希望这对像我这样的人有所帮助。
自定义绑定 方法是这里的关键。真正有用的东西在这里:
In MvvmCross how do I do custom bind properties
MVVMCross Bindings in Android
所以,就我而言,为了让应用程序监听 SeekBar
OnStopTrackingTouch
事件,我这样做了:
已创建绑定 class:
public class SeekbarStopTrackingTouchEventBinding: MvxAndroidTargetBinding
{
private readonly SeekBar _seekbar;
private IMvxAsyncCommand<SeekBar.StopTrackingTouchEventArgs> _command;
private string testString;
public SeekbarStopTrackingTouchEventBinding(SeekBar seekbar) : base(seekbar)
{
_seekbar = seekbar;
_seekbar.StopTrackingTouch += ViewOnStopTrackingTouch;
}
private void ViewOnStopTrackingTouch(object sender, SeekBar.StopTrackingTouchEventArgs e)
{
if (_command != null)
{
_command.Execute(e);
}
}
public override Type TargetType
{
get { return typeof (IMvxAsyncCommand); }
}
protected override void SetValueImpl(object target, object value)
{
try
{
_command = (IMvxAsyncCommand<SeekBar.StopTrackingTouchEventArgs>)value;
}
catch (Exception e)
{
Log.Error("SOME BINDER FAIL\n\t" + e.Message + "\n", "SOME BINDER FAIL\n\t" + e.Message + "\n");
throw;
}
}
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
_seekbar.StopTrackingTouch -= ViewOnStopTrackingTouch;
}
base.Dispose(isDisposing);
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.OneWay; }
}
}
在 Setup.cs
中放置此代码:
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
base.FillTargetFactories(registry);
registry.RegisterFactory(new MvxCustomBindingFactory<SeekBar>("OnStopTrackingTouch", (seekbar) => new SeekbarStopTrackingTouchEventBinding(seekbar)));
}
在我的 ViewModel
和命令执行函数中准备 属性:
public IMvxAsyncCommand<SeekBar.StopTrackingTouchEventArgs> PlayProgressChanged
{
get
{
return new MvxAsyncCommand<SeekBar.StopTrackingTouchEventArgs>(OnPlayProgressChange);
}
}
private async Task OnPlayProgressChange(SeekBar.StopTrackingTouchEventArgs e)
{
var progr = e.SeekBar.Progress;
await _playingService.SetTime((int) progr).ConfigureAwait(false);
}
在视图布局中,在 local:MvxBind
内将我的 ViewModel
命令与 Setup.cs
registry.RegisterFactory
中提供的事件名称相关联
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/playprogress"
local:MvxBind="Progress ValueOfTimer; OnStopTrackingTouch PlayProgressChanged"
/>