MVVMCross Привязка десятичной дроби к UITextField удаляет десятичную точку

Привязка десятичной дроби к UITextField не позволяет вам ставить "." in, когда вы набираете «1», нажатие на источник удаляет его. Я понимаю, почему это происходит, MakeSafeValue преобразует его в десятичное число, которое считывается обратно без ".", Перезаписывая введенный текст. Это похоже на проблему с клавиатурой и onblur, которую многие связывающие фреймворки позволяют вам переопределить.

Я знаю, что мог бы вместо этого привязать строку к модели представления, но обработка EditingDidEnd вместо EditingChanged кажется лучше. Таким образом, я мог перехватить ShouldEndEditing для проверки действительности.

Где мне зарегистрировать привязку, чтобы переопределить реализацию MvvmCross? Я попытался добавить в свой Setup.FillTargetFactories, но он вызывается до MVXTouchBindingBuilder.FillTargetFactories, где находится MvvmCross.

Я пробовал другое имя свойства, в FillTargetFactories у меня есть:

registry.RegisterPropertyInfoBindingFactory(typeof (UITextFieldTextDidEndTargetBinding), typeof (UITextField), "DidEndText");

но при привязке не работает.

set.Bind(textField).For("DidEndText").To(vm => vm.GMoney);

похоже, что MvxPropertyInfoTargetBindingFactory.CreateBinding не работает, если у цели нет этого свойства = имеет смысл. Остается ли мне начать с MvxTargetBinding и создать настраиваемую привязку? Ненавижу воссоздавать большую часть кода в MvxPropertyInfoTargetBinding.

Итак, я предполагаю, что вопрос (ы) в том ...

  • каков синтаксис / местоположение, чтобы переопределить привязку UITextField по умолчанию с моей?
  • как я могу указать другую привязку для текста с синтаксисом привязки?

Заранее спасибо.


person Brian Chance    schedule 11.07.2013    source источник


Ответы (1)


каков синтаксис / местоположение, чтобы переопределить привязку UITextField по умолчанию с моей?

Если вы хотите просто заменить существующую привязку, вы можете сделать это с помощью метода расширения RegisterPropertyInfoBindingFactory.

MvvmCross использует простую систему «последних зарегистрированных побед».

Самый простой способ разместить вашу регистрацию, чтобы она происходила в последнюю очередь, - это поместить ее в конец InitializeLastChance в вашем Setup:

 protected override void InitializeLastChance()
 {
     base.InitializeLastChance();

     var factory = base.Resolve<IMvxTargetBindingFactoryRegistry>();
     factory.RegisterPropertyInfoBindingFactory(
                     typeof(MyBindingType),
                     typeof(UITextField),
                     "Text");
 }

Дополнительные сведения о порядке инициализации / настройки см. В https://github.com/slodge/MvvmCross/wiki/Customising-using-App-and-Setup (в стадии разработки).

как я могу указать другую привязку для текста с синтаксисом привязки?

Линия:

     registry.RegisterPropertyInfoBindingFactory(
            typeof (UITextFieldTextDidEndTargetBinding), 
            typeof (UITextField), 
            "DidEndText");

не работает, потому что пытается использовать свойство с именем DidEndText, которого не существует.

Есть два возможных способа обойти это:

1 подкласс UITextField для предоставления недвижимости

   public class MyTextField : UITextField
   {
        // ctors

        public string MySpecialText
        {
            get { return base.Text; }
            set { base.Text = value; }
        }
   }

Пример подкласса UITextField показан в видео N = 33

2 Или используйте привязку не на основе propertyInfo

Для известных свойств и пар событий это довольно просто сделать:

public class MySpecialBinding : MvxTargetBinding
{
    public MySpecialBinding (UIEditField edit)
        : base(edit)
    {
        edit.SpecialEvent += Handler;
    }

    protected override void Dispose(bool isDisposing)
    {
        if (isDisposing)
        {
            var text = (UITextField)Target;
            if (text != null)
            {
                text.SpecialEvent -= Handler;
            }
        }
        base.Dispose(isDisposing);
    }

    protected override void Handler(object s, EventArgs e)
    {
        var text = (UITextField)target;
        if (text == null)
            return;
        FireValueChanged(text.Text);
    }

    public override MvxBindingMode DefaultMode
    {
        get { return MvxBindingMode.TwoWay; }
    }

    public override Type TargetType
    {
        get { return typeof(string); }
    }

    public override void SetValue(object value)
    {
        var text = (UITextField)target;
        if (text == null)
            return;
        text.Text = value;
    }
}

Эту специальную привязку можно зарегистрировать с помощью RegisterCustomBindingFactory

registry.RegisterCustomBindingFactory<UITextField>(
        "FooFlipper", 
        textField => new MySpecialBinding(textField));

После чего привязки вроде:

set.Bind(textField).For("FooFlipper").To(vm => vm.GMoney);

буду работать.


Помимо вашего предложения «использовать строку в модели представления», еще одним возможным обходным путем для этого преобразования двойного текста может быть использование двустороннего преобразователя значений. Если ваш пользовательский интерфейс обрабатывает деньги, он может настаивать на отображении десятичных знаков для всех значений.

person Stuart    schedule 12.07.2013
comment
И последнее - для вашей конкретной проблемы / задачи, я думаю, MvvmCross будет заинтересован в исправлениях / предложениях, если вы можете придумать какие-либо ... (хотя сначала я также выделю немного времени, чтобы настроить для этого тестовую привязку - не кое-что, что я видел раньше, например, в tipcalc) - person Stuart; 12.07.2013
comment
Я создал репозиторий, чтобы показать некоторые способы решения проблемы: github.com/brianchance/MonoTouchMVVMCrossValidationTester, пусть я знаю, если непонятно. Во время этого упражнения узнал много нового о MVVMCross. - person Brian Chance; 12.07.2013
comment
Некоторые предложения, которые я могу придумать, заключаются в том, чтобы разрешить передачу параметров связыванию из синтаксиса связывания (например, Changing vs EndEdit), чтобы они могли быть более гибкими. Что-то вроде set.Bind (field) .Options (new {EndEdit = true}). To (vm = ›vm.SomeField) ;, Еще одно предложение - публиковать ошибки преобразования с помощью мессенджера или подключать событие, чтобы можно было дать обратную связь . - person Brian Chance; 12.07.2013