Я пытаюсь достичь идеального MVVM в Xamarin.Forms со Entry.Двусторонняя вяжущая запись, которая поддерживает базовые типы и типы с нулевым значением
В моей модели содержатся свойства, тип которых включает строку, int ?, decimal ?, bool ?, etc. Всякий раз, когда я привязываюсь к строковому типу, двухсторонняя привязка работает, потому что свойство text имеет тип строки (они соответствуют). Но как только вы попытаетесь привязать себя к модели, а свойство - int или int?, Оно не обновляет значение свойства модели.
В ходе моих исследований и с помощью поддержки Xamarin, это был очень полезный нить о том, как обрабатывать NULLABLE типов:
Nullable type in x:TypeArguments
XAML код:
<controls:NullableIntEntry Grid.Column="1" Grid.Row="14" NumericText="{Binding BusinessOwnership, Mode=TwoWay}" x:Name="lblBusinessOwnership"></controls:NullableIntEntry>
BindableEntry (Расширение ввода) код:
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Reflection;
using Xamarin.Forms;
namespace CreditBuilderApp.Controls
{
public class BindableEntry<T> : Entry
{
static bool firstLoad;
public static readonly BindableProperty NumericTextProperty =
BindableProperty.Create("NumericText", typeof(T), typeof(BindableEntry<T>),
null, BindingMode.TwoWay, propertyChanged: OnNumericTextChanged);
static void OnNumericTextChanged(BindableObject bindable, object oldValue, object newValue)
{
var boundEntry = (BindableEntry<T>)bindable;
if (firstLoad && newValue != null)
{
firstLoad = false;
boundEntry.Text = newValue.ToString();
}
}
public T NumericText
{
get { return (T)GetValue(NumericTextProperty); }
set { SetValue(NumericTextProperty, value); }
}
public BindableEntry()
{
firstLoad = true;
this.TextChanged += BindableEntry_TextChanged;
}
private void BindableEntry_TextChanged(object sender, TextChangedEventArgs e)
{
if (!String.IsNullOrEmpty(e.NewTextValue))
{
this.NumericText = (T)Convert.ChangeType(e.NewTextValue, typeof(T));
}
else
{
this.NumericText = default(T);
}
}
}
}
NullableIntEntry и (расширение Bindable запись с указанием типа) NullableDecimalEntry:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CreditBuilderApp.Controls
{
public class NullableIntEntry : BindableEntry<Int32?>
{
}
public class NullableDecimalEntry : BindableEntry<Decimal?>
{
}
}
Модель:
private int? _businessOwnership { get; set; }
public int? BusinessOwnership
{
get { return _businessOwnership; }
set
{
if (_businessOwnership != value)
{
_businessOwnership = value;
RaisePropertyChanged();
}
}
}
Я на самом деле способен связываться с целым, десятичной, поплавки, в основном любой тип, который не является строкой, которая является шагом в правильном направлении. НО, для этого я должен создать BindableEntry выше и указать, какой тип он есть. (Заменить Т с междунар ?, T с десятичной ?, и т.д. ,. наряду с указанием, как e.NewTextValue отливают
ПРОБЛЕМА:. Преобразование ниже изменение типа ломает два способа связывания
this.NumericText = (T)Convert.ChangeType(e.NewTextValue, typeof(T));
Но это дает мне ошибку (очевидно), так как this.NumericText имеет тип T до времени выполнения.
Так что, если я хотел запись работать обнуляемого чисел, я должен был бы заменить весь тип T с int? А также изменить приведенный выше код:
Convert.ToInt32(e.NewTextValue)
Когда я шаг через код, всякий раз, когда я достичь Convert.ChangeType до Т линии, он выходит из кадра. Нет ошибки, и страница отображается, но каждый элемент управления после этой конкретной записи с возможностью связывания не имеет значений.
After stepping through the ConvertType function
Позвольте мне знать, если я пропустил какую-либо информацию. Помощь будет оценена!
Преобразователи ценности работают, но не для типов с нулевым значением. Итак, если я конвертирую между int? (Nullable) и строкой, я не могу вернуть null. Что заставляет работать, если я возвращаю default (int), который равен 0. –
TonyMykhaylovsky
@TonyMykhaylovsky, я не уверен, что вы имеете в виду, когда вы говорите, что преобразователи значений не работают с типами с нулевым значением. Конечно, они делают, тип возврата и параметр 'value' имеют тип' object'. Если вы передадите тип значения, например 'int', он будет помещен в поле' object', что уменьшит необходимость преобразования вручную из int? и непустые типы. – ethane