#c# #wpf
Вопрос:
У меня есть класс со сложными свойствами, которые привязаны к моим элементам управления пользовательского интерфейса. Класс может быть преобразован по желанию в строку и из нее. Как я могу правильно привязать этот класс к текстовому полю?
[TypeConverter(typeof(LatLongTypeConverter))]
public class LatLong : IComparable, IXmlSerializable
{
.
.
.
public override string ToString() {...}
public static implicit operator LatLong(string L) {...}
public static explicit operator string(LatLong L) {...}
public class LatLongTypeConverter : TypeConverter
{
.
.
.
}
}
public class City : INotifyPropertyChanged
{
private string _Name = "Chicago";
private LatLong _Location = "41.52N 87.37W";
public string Name
{
get => _Name;
set { _Name = value; Notify(); }
}
public LatLong Location
{
get => _Location;
set { _Location = value; Notify(); }
}
public event PropertyChangedEventHandler PropertyChanged;
public void Notify([System.Runtime.CompilerServices.CallerMemberName] string PropertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
}
}
XAML:
<TextBlock Text="{Binding Location}"/>
Как заставить текстовый блок отображать «41.52 N 87.37 Вт» без использования преобразователя Ivaluecon? В настоящее время преобразование типов отлично работает в коде, но при привязке оно просто отображает пустое поле.
Комментарии:
1. В XAML преобразователь типов вызывается (процессором XAML) только тогда, когда вы сопоставляете строку с нестроковым свойством-в вашем случае LatLong. Затем обработчик XAML будет использовать конвертер для преобразования строки в экземпляр LatLong. Но поскольку вы напрямую привязываетесь к экземпляру LatLong, вам необходимо использовать преобразователь ivaluecon или добавить свойство LatLong.displayValue типа string к вашему типу (и использовать его в качестве источника привязки). Расширение разметки привязки не знает, как преобразовать экземпляр LatLong в экземпляр строки. Вы должны позаботиться об этом.
Ответ №1:
WPF нужен только TextBlock
текст для привязки к строке, для чего-либо более сложного, чем это, требуется прямая привязка конвертера. Что оставляет два варианта: создайте экземпляр IValueConverter
, который берет LatLong
экземпляр и возвращает строку, например, вызывая ее неявное преобразование, или сделайте это в своем коде за/viewmodel/сервер, к которому вы привязываетесь.
Здесь я покажу очень простой способ сделать второй вариант, добавив дополнительное свойство для привязки WPF к:
//New property for WPF to bind to, simply takes the full object and uses it's implicit string conversion
public string LocationString => (string)this.Location;
public LatLong Location
{
get => _Location;
//Here we notify changes of both properties, as one is calculated from the other
set { _Location = value; Notify(); Notify("LocationString"); }
}
Затем просто измените привязку к новому свойству в XAML:
<TextBlock Text="{Binding LocationString}"/>
Комментарии:
1. Вам следует подумать о том, чтобы добавить свойство LocationString в тип LatLong (как свойство только для чтения, например, с набором частных свойств (). Это делает тип LatLong более удобным для (повторного)использования.