WinRT, обвързване на TextBox в MVVM

WinRT --- Свързване на текстово поле в MVVM

Едно от основните предимства на разделянето на бизнес логиката с модела MVVM е възможността за пълно препроектиране на потребителския интерфейс без промяна на модела на изгледа. Да приемем, че вашата програма ви позволява да избирате цветове, подобни на приложението ColorScroll, обсъдено по-рано, но цветовите компоненти се въвеждат в TextBoxes. Работата с такава програма няма да бъде много удобна, но възможна.

Следващият проект използва същия клас RgbViewModel, както преди. В допълнение, кодът зад файла съдържа същия конструктор като в този проект:

XAML файлът инстанцира три контроли TextBox и дефинира обвързвания на данни между свойствата Red, Green и Blue на обекта RgbViewModel:

Когато програмата стартира, контролите на TextBox се инициализират със стойностите на цветните компоненти и всички необходими трансформации на данни се извършват тихо.

mvvm

Сега опитайте да докоснете контролата TextBox и да въведете различно число. Нищо не се случва. Сега докоснете друг елемент на TextBox или натиснете клавиша Tab, за да дадете фокус на въвеждането. Аха! Сега числото, въведено в първото TextBox, се приема и използва за актуализиране на цвета.

Докато експериментирате с тази програма, ще откриете, че Windows Runtime е доста снизходителен по отношение на въвеждането на букви и знаци в текстови полета и не хвърля изключение, но всяка въведена стойност се регистрира само когато TextBox загуби фокуса на въвеждане.

За съжаление това поведение не може да бъде променено в момента. Също така няма начин да включите валидиране на данни в обвързването. Ако това поведение на обвързването на TextBox е неприемливо за вас и не искате да дублирате логикатаTextBox в собствения си контрол, единствената останала опция е да премахнете обвързванията и да използвате инструмента за обработка на събития TextChanged.

Едно възможно решение е демонстрирано в следния проект. Той също така използва класа RgbViewModel. XAML файлът е подобен на файла от предишния проект, с изключение на това, че контролите на TextBox вече са наименувани и са присвоени манипулатори TextChanged:

Елементът Rectangle обаче съдържа същите обвързвания като в предишните програми.

Тъй като заменяме двупосочните обвързвания, ще ни трябват не само манипулатори на събития за елементите TextBox, но също и манипулатор на събития PropertyChanged за обекта RgbViewModel. Не е трудно да се организира актуализация на TextBox, когато се промени свойството на модел на изглед, но също така реших да добавя проверка за текста, въведен от потребителя:

Val метод > TryParse() метод за преобразуване на текст в байтова стойност. Ако преобразуването е успешно, моделът на изгледа се актуализира, а ако не, текстът се показва с червен шрифт, привличайки вниманието на потребителя към проблема.

Това решение също работи добре, ако числата се въвеждат с водещи интервали или нули. Да приемем, че сте въвели 0 в първото текстово поле. Това е валидна байтова стойност, така че свойството Red на RgbViewModel се актуализира с въведената стойност; това кара метода PropertyChanged да се активира и стойността "0" от тип Text се въвежда в TextBox. Всичко е наред. Сега въведете числото 5. TextBox съдържа низа "05". Методът TryParse счита въведената стойност за валидно представяне на низ за типа байт и свойството Red се актуализира със стойност 5.

Манипулаторът PropertyChanged сега задава свойството Text на TextBox на стойността на низа "5", замествайки "05".Но позицията на курсора не се променя, така че сега се намира преди числото 5, а не след него.

Може би по-добро решение на този проблем би било да се игнорират събитията PropertyChanged, когато се задава свойството на модела на изглед в манипулатора TextChanged.

Проблемът се решава чрез просто задаване на флага:

В някои ситуации валидирането на входа е най-добре поставено под юрисдикцията на модела на изгледа (а не на изгледа).