У меня есть текстовое поле WPF в форме, чтобы разрешить ввод URI.
Я попытался сделать это с помощью конвертера данных.Проблема заключается в том, что когда привязка текстового поля обновляется, а текстовое поле не содержит действительного URI,
- Преобразователь данных возвращает значение NULL;
- , который устанавливает для свойства моей модели значение NULL;
- , что приводит к запуску события, изменяющего свойство;
- , который устанавливает значение текстового поля в пустую строку, стирая недопустимый ввод пользователя
I'mновичок WPF, и я затрудняюсь найти простой шаблон, использующий конвертер данных, который не приводит к такому поведению.Я думаю, что должен быть стандартный шаблон для использования, о котором я знал бы, если бы я был опытным программистом WPF.
Глядя на примеры, включенные в Prism 4, кажется, что используются два различных подхода.,Мне они оба не нравятся.
Первый подход - генерировать исключение, когда для моего свойства модели задано значение null, которое перехватывается и отображается как ошибка проверки.Проблема заключается в том, что я хочу, чтобы свойство могло иметь значение null - каждый раз, когда вы открываете форму, поля устанавливаются в свои предыдущие значения.Если приложение никогда ранее не запускалось, для URI будет установлено значение null - это не должно вызывать исключения.Кроме того, использование исключений для проверки является уродливым.
Второй подход заключается в том, что когда для свойства задано значение NULL, задайте состояние проверки модели для включения недействительности свойства, но на самом деле не обновляйте свойство,Который я считаю ужасным.Это приводит к тому, что модель является внутренне несовместимой, утверждая, что DCSUri недействителен, но содержит предыдущее допустимое значение DCSUri.
Подход, который я использую, чтобы избежать этих проблем, заключается в том, чтобы в моем ViewModel была строка DCSUri., который обновляет свойство DCSUri, введенное в Uri моей Модели, только если это действительный URI.Но я бы предпочел подход, который позволяет использовать конвертер и привязывать мое текстовое поле непосредственно к моей модели.
Код моего конвертера:
/// <summary>
/// Converter from Uri to a string and vice versa.
/// </summary>
public class StringToUriConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
Uri uri = null;
string stringValue = value as string;
if (stringValue != null)
Uri.TryCreate(stringValue, UriKind.Absolute, out uri);
return uri;
}
}
XAML для текстового поля:
<TextBox Grid.Row="1" Grid.Column="1" Name="DCSUriTextBox"
Text="{Binding Path=DCSLoadSettings.DCSUri, Mode=TwoWay, UpdateSourceTrigger=LostFocus, ValidatesOnExceptions=True, NotifyOnValidationError=True, ValidatesOnDataErrors=True, Converter={StaticResource StringToUriConverter} }"
HorizontalAlignment="Stretch" Height="Auto" VerticalAlignment="Center" Margin="5,0,20,0" IsReadOnly="{Binding Path=IsNotReady}" Grid.ColumnSpan="2" />
И код свойства DCSUri в моей модели:
/// <summary>
/// The Uri of the DCS instance being provided configuration
/// </summary>
public Uri DCSUri
{
get
{
return mDCSUri;
}
set
{
if (!Equals(value, mDCSUri))
{
mDCSUri = value;
this["DCSUri"] = value == null
? "Must provide a Uri for the DCS instance being provided configuration"
: string.Empty;
RaisePropertyChanged(() => DCSUri);
}
}
}