2016-11-01 2 views
0

у нас есть проблемы с преобразователями в MvvmCross в связи с блоком управления EditText в Android:MvvmCross Android конвертер вызывает курсор прыгать

В нашем приложении, пользователь вставляет пользовательские данные. Мы должны сделать некоторые вычисления с этими данными в конвертере, а затем записать данные в нашей модели viewmodel.

Это работает, если пользователь не возвращает свою запись. Это означает, что если он использует обратную клавишу, значение будет правильно отредактировано, пока не достигнет последнего десятичного знака до «.». (например: 55,99, когда он достигает «55,9»). «.9» будет удалено правильно, но куросоры скачут оставшиеся «55». Как мы можем разрешить это раздражающее поведение?

ViewModel экстракт:

private Nullable mdValue1 = null; 

public Nullable<decimal> Value1 
{ 
    get { return mdValue1; } 
    set 
    { 
    SetProperty(ref mdValue1, value); 
    } 
} 

private Nullable<decimal> mdValue2; 

public Nullable<decimal> Value2 
{ 
    get { return mdValue2; } 
    set 
    { 

     SetProperty(ref mdValue2, value, nameof(Value2)); 

    } 
} 

конвертер (упрощенный):

public class DecimalToStringValueConverter : MvxValueConverter<Nullable<decimal>, string> 
{ 
protected override string Convert(Nullable<decimal> poValue, Type poTargetType, object poParameter, CultureInfo poCulture) 
{ 
    if (!poValue.HasValue) 
    { 
     return null; 
    } 

    return poValue.Value.ToString(); 
} 

protected override Nullable<decimal> ConvertBack(string value, Type targetType, object parameter, CultureInfo culture) 
{ 
    if (string.IsNullOrWhiteSpace(value)) 
    { 
     return null; 
    } 

    return decimal.Parse(value); 
} 
} 

Конфигурация

Android Версия: 4.4/5.1/7

Платформа: Xamarin

ответ

1

Кажется, что происходит, когда точка удаляется и преобразуется в десятичное, в результате изменения значения в ViewModel тогда отличается от EditText вызывая ViewModel, чтобы установить значение из Редактировать текст.

Пример: Пользователь вводит 59.9 затем 9 забоя. Это оставляет значение в EditText как 59., которое анализируется как десятичное число до 59 в ViewModel. Так как 59. не равен 59, ViewModel обновит значение в EditText до 59, это заставляет курсор перейти к началу.

Одним из быстрых способов решения этой проблемы является создание настраиваемой привязки, которая гарантирует, что курсор всегда будет помещен в конец EditText после удаления последнего десятичного знака. Это можно сделать, используя SetSelection, который позиционирует курсор в методе SetValueImpl.

public class DecimalEditTextTargetBinding : MvxConvertingTargetBinding 
{ 
    protected EditText EditTextControl => Target as EditText; 

    private IDisposable _subscription; 

    public DecimalEditTextTargetBinding(EditText target) : base(target) 
    { 
     if (target == null) 
      MvxBindingTrace.Error($"Error - EditText is null in {nameof(DecimalEditTextTargetBinding)}"); 
    } 

    public override Type TargetType => typeof(string); 
    public override MvxBindingMode DefaultMode => MvxBindingMode.TwoWay; 

    protected override void SetValueImpl(object target, object value) 
    { 
     ((TextView)target).Text = (string)value; 
     EditTextControl.SetSelection(EditTextControl.Text?.Length ?? 0); 
    } 

    public override void SubscribeToEvents() 
    { 
     if (EditTextControl == null) 
      return; 

     _subscription = EditTextControl.WeakSubscribe<TextView, AfterTextChangedEventArgs>(
      nameof(EditTextControl.AfterTextChanged), 
      EditTextOnAfterTextChanged); 
    } 

    private void EditTextOnAfterTextChanged(object sender, AfterTextChangedEventArgs e) 
    { 
     FireValueChanged(EditTextControl.Text); 
    } 

    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.RegisterCustomBindingFactory<EditText>("DecimalText", inputField => new DecimalEditTextTargetBinding(inputField)); 
} 

XML:

<EditText 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:inputType="numberDecimal|numberSigned" 
    local:MvxBind="DecimalText DecimalToString(Value1)" /> 

Пример связывания для предварительного MvvmCross 4.4.0:

public class DecimalEditTextTargetBinding : MvxConvertingTargetBinding 
{ 
    private bool _subscribed; 

    public DecimalEditTextTargetBinding(EditText target) : base(target) 
    { 
     if (target == null) 
      MvxBindingTrace.Error($"Error - EditText is null in {nameof(DecimalEditTextTargetBinding)}"); 
    } 

    protected EditText EditTextControl => Target as EditText; 

    public override Type TargetType => typeof(string); 

    public override MvxBindingMode DefaultMode => MvxBindingMode.TwoWay; 

    protected override void SetValueImpl(object target, object value) 
    { 
     ((TextView)target).Text = (string)value; 
     EditTextControl.SetSelection(EditTextControl.Text?.Length ?? 0); 
    } 

    public override void SubscribeToEvents() 
    { 
     if (EditTextControl == null) 
      return; 

     EditTextControl.AfterTextChanged += EditTextOnAfterTextChanged; 
     _subscribed = true; 
    } 

    private void EditTextOnAfterTextChanged(object sender, AfterTextChangedEventArgs e) 
    { 
     FireValueChanged(EditTextControl.Text); 
    } 

    protected override void Dispose(bool isDisposing) 
    { 
     if (isDisposing && EditTextControl != null && _subscribed) 
     { 
      EditTextControl.AfterTextChanged -= EditTextOnAfterTextChanged; 
      _subscribed = false; 
     } 

     base.Dispose(isDisposing); 
    } 
} 
+0

Привет! Прежде всего, спасибо за ваше время! Вы нам очень помогли, мы довольно новичок в Xamarin. Теперь курсор работает.Другая проблема возникла с «WeakSubscribe». Он не может быть найден и отмечен красным. Есть ли сборка для использования? – Mephistopheles

+0

«WeakSubscribe» доступен в разделе «MvvmCross.Platform.WeakSubscription», который был добавлен в [Mvvmcross 4.4.0.] (Https://github.com/MvvmCross/MvvmCross/commit/b2e67d8994859cd68d42fb87a287eb462a44ba49) Если вы на старшей вы можете вместо этого подписаться непосредственно на 'AfterTextChanged'. Я обновлю ответ, чтобы включить пример. – Plac3Hold3r

+0

Теперь мы на 4.4, и это работает! Большое вам спасибо, очень ценю! – Mephistopheles