I got sort of a typical music player window, music plays and seekbar point is moving while it plays.
I've done it using default mvvmcross
binding to the property (which is changed through the EventHandler
binding) like here:
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/playprogress"
local:MvxBind="Progress ValueOfTimer"
/>
So now I want the user to be able to move it forward and back.
I've been trying to bind it like this:
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);
}
}
Viewmodel part looks like this:
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);
}
}
But looks like it's not working.
I mean, it's not even getting into OnPlayProgressChange
. But on view is appearing it goes into command PlayProgressChanged
one time.
How can I bind this event (and such kind of events like StartTrackingTouch
, StopTrackingTouch
) to the function correctly?
P.S. just FYI I using MvvmCross 5
UPD 28.11.2017
Tried custom binding and even Progress
binding stoped working now.
So, xaml looks like this now:
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/playprogress"
local:MvxBind="Progress ValueOfTimer, OnStopTrackingTouch PlayProgressChanged"
/>
And binder code is here
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; }
}
}
}
In Setup:
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
base.FillTargetFactories(registry);
registry.RegisterFactory(new MvxCustomBindingFactory<SeekBar>("OnStopTrackingTouch", (seekbar) => new SeekbarStopTrackingTouchEventBinding(seekbar)));
}
UPD2
Changed binding like this: local:MvxBind="Progress ValueOfTimer; OnStopTrackingTouch PlayProgressChanged"
(notice ;
here) and event fires now, yes!
But now the thing is - in binder
_command
is stays null even after SetValueImpl
fired and _command = (IMvxAsyncCommand)value;
is fine, value
points to setted ViewModel property.
How come?
UPD3
Found out it can't cast object
to IMvxAsyncCommand
.
I fixed that by changing
IMvxAsyncCommand _command
to IMvxAsyncCommand<SeekBar.StopTrackingTouchEventArgs> _command
;
Will sum everything up in the answer.
But now I got the question - whats best practice in this case?