wpf
Ценностные и многозначные преобразователи
Поиск…
параметры
параметр | подробности |
---|---|
значение | Значение, полученное источником связывания. |
ценности | Массив значений, созданный источником связывания. |
TargetType | Тип целевого свойства привязки. |
параметр | Используемый параметр преобразователя. |
культура | Культура для использования в конвертере. |
замечания
Что такое IValueConverter и IMultiValueConverterthey
IValueConverter и IMultiValueConverter - интерфейсы, которые обеспечивают способ применения пользовательской логики к привязке.
Что они полезны для
- У вас есть какое-то значение типа, но вы хотите показать нулевые значения одним способом и положительные числа по-другому
- У вас есть какое-то значение типа и вы хотите показать элемент в одном случае и спрятать в другом
- У вас есть числовое значение денег, но вы хотите показать это как слова
- У вас есть числовое значение, но вы хотите показать разные изображения для дефрантных чисел
Это некоторые из простых случаев, но их гораздо больше.
Для таких случаев вы можете использовать преобразователь значений. Эти небольшие классы, которые реализуют интерфейс IValueConverter или IMultiValueConverter, будут действовать как посредники и переводят значение между источником и пунктом назначения. Таким образом, в любой ситуации, когда вам нужно преобразовать значение до того, как оно снова достигнет цели или вернется к его источнику, вам, вероятно, понадобится конвертер.
Встроенный BooleanToVisibilityConverter [IValueConverter]
Конвертер между булевым и видимым. Получить значение bool
для ввода и Visibility
значение Visibility
.
ПРИМЕЧАНИЕ. Этот конвертер уже существует в System.Windows.Controls
имен System.Windows.Controls
.
public sealed class BooleanToVisibilityConverter : IValueConverter
{
/// <summary>
/// Convert bool or Nullable bool to Visibility
/// </summary>
/// <param name="value">bool or Nullable bool</param>
/// <param name="targetType">Visibility</param>
/// <param name="parameter">null</param>
/// <param name="culture">null</param>
/// <returns>Visible or Collapsed</returns>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
bool bValue = false;
if (value is bool)
{
bValue = (bool)value;
}
else if (value is Nullable<bool>)
{
Nullable<bool> tmp = (Nullable<bool>)value;
bValue = tmp.HasValue ? tmp.Value : false;
}
return (bValue) ? Visibility.Visible : Visibility.Collapsed;
}
/// <summary>
/// Convert Visibility to boolean
/// </summary>
/// <param name="value"></param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns></returns>
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is Visibility)
{
return (Visibility)value == Visibility.Visible;
}
else
{
return false;
}
}
}
Использование преобразователя
- Определить ресурс
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
- Используйте его в привязке
<Button Visibility="{Binding AllowEditing,
Converter={StaticResource BooleanToVisibilityConverter}}"/>
Конвертер с свойством [IValueConverter]
Покажите, как создать простой конвертер с параметром через свойство, а затем передать его в объявлении. Преобразование значения bool
в Visibility
. Разрешить инвертировать значение результата, установив Inverted
свойство в значение True
.
public class BooleanToVisibilityConverter : IValueConverter
{
public bool Inverted { get; set; }
/// <summary>
/// Convert bool or Nullable bool to Visibility
/// </summary>
/// <param name="value">bool or Nullable bool</param>
/// <param name="targetType">Visibility</param>
/// <param name="parameter">null</param>
/// <param name="culture">null</param>
/// <returns>Visible or Collapsed</returns>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
bool bValue = false;
if (value is bool)
{
bValue = (bool)value;
}
else if (value is Nullable<bool>)
{
Nullable<bool> tmp = (Nullable<bool>)value;
bValue = tmp ?? false;
}
if (Inverted)
bValue = !bValue;
return (bValue) ? Visibility.Visible : Visibility.Collapsed;
}
/// <summary>
/// Convert Visibility to boolean
/// </summary>
/// <param name="value"></param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns>True or False</returns>
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is Visibility)
{
return ((Visibility) value == Visibility.Visible) && !Inverted;
}
return false;
}
}
Использование преобразователя
- Определение пространства имен
xmlns:converters="clr-namespace:MyProject.Converters;assembly=MyProject"
- Определить ресурс
<converters:BooleanToVisibilityConverter x:Key="BoolToVisibilityInvertedConverter"
Inverted="False"/>
- Используйте его в привязке
<Button Visibility="{Binding AllowEditing, Converter={StaticResource BoolToVisibilityConverter}}"/>
Простой добавочный конвертер [IMultiValueConverter]
Покажите, как создать простой конвертер IMultiValueConverter
и использовать MultiBinding
в xaml. Получите суммирование всех значений, переданных массивом values
.
public class AddConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
decimal sum = 0M;
foreach (string value in values)
{
decimal parseResult;
if (decimal.TryParse(value, out parseResult))
{
sum += parseResult;
}
}
return sum.ToString(culture);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
Использование преобразователя
- Определение пространства имен
xmlns:converters="clr-namespace:MyProject.Converters;assembly=MyProject"
- Определить ресурс
<converters:AddConverter x:Key="AddConverter"/>
- Используйте его в привязке
<StackPanel Orientation="Vertical">
<TextBox x:Name="TextBox" />
<TextBox x:Name="TextBox1" />
<TextBlock >
<TextBlock.Text>
<MultiBinding Converter="{StaticResource AddConverter}">
<Binding Path="Text" ElementName="TextBox"/>
<Binding Path="Text" ElementName="TextBox1"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
Преобразователи с конвертером
Покажите, как создать простой конвертер и использовать ConverterParameter
для передачи параметра в конвертер. Значение умножения по коэффициенту, переданному в ConverterParameter.
public class MultiplyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return 0;
if (parameter == null)
parameter = 1;
double number;
double coefficient;
if (double.TryParse(value.ToString(), out number) && double.TryParse(parameter.ToString(), out coefficient))
{
return number * coefficient;
}
return 0;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
Использование преобразователя
- Определение пространства имен
xmlns:converters="clr-namespace:MyProject.Converters;assembly=MyProject"
- Определить ресурс
<converters:MultiplyConverter x:Key="MultiplyConverter"/>
- Используйте его в привязке
<StackPanel Orientation="Vertical">
<TextBox x:Name="TextBox" />
<TextBlock Text="{Binding Path=Text,
ElementName=TextBox,
Converter={StaticResource MultiplyConverter},
ConverterParameter=10}"/>
</StackPanel>
Групповые мультиконвертеры [IValueConverter]
Этот преобразователь объединяет несколько преобразователей.
public class ValueConverterGroup : List<IValueConverter>, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return this.Aggregate(value, (current, converter) => converter.Convert(current, targetType, parameter, culture));
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
В этом примере логический результат из EnumToBooleanConverter
используется в качестве входа в BooleanToVisibilityConverter
.
<local:ValueConverterGroup x:Key="EnumToVisibilityConverter">
<local:EnumToBooleanConverter/>
<local:BooleanToVisibilityConverter/>
</local:ValueConverterGroup>
Кнопка будет видна только тогда, когда для свойства CurrentMode
установлено значение « Ready
.
<Button Content="Ok" Visibility="{Binding Path=CurrentMode, Converter={StaticResource EnumToVisibilityConverter}, ConverterParameter={x:Static local:Mode.Ready}"/>
Использование MarkupExtension с конвертерами для пропуска декларации ресурсов
Обычно для использования конвертера мы должны определить его как ресурс следующим образом:
<converters:SomeConverter x:Key="SomeConverter"/>
Этот шаг можно пропустить, MarkupExtension
преобразователь как MarkupExtension
и реализуя метод ProvideValue
. Следующий пример преобразует значение в отрицательный:
namespace MyProject.Converters
{
public class Converter_Negative : MarkupExtension, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return this.ReturnNegative(value);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return this.ReturnNegative(value);
}
private object ReturnNegative(object value)
{
object result = null;
var @switch = new Dictionary<Type, Action> {
{ typeof(bool), () => result=!(bool)value },
{ typeof(byte), () => result=-1*(byte)value },
{ typeof(short), () => result=-1*(short)value },
{ typeof(int), () => result=-1*(int)value },
{ typeof(long), () => result=-1*(long)value },
{ typeof(float), () => result=-1f*(float)value },
{ typeof(double), () => result=-1d*(double)value },
{ typeof(decimal), () => result=-1m*(decimal)value }
};
@switch[value.GetType()]();
if (result == null) throw new NotImplementedException();
return result;
}
public Converter_Negative()
: base()
{
}
private static Converter_Negative _converter = null;
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (_converter == null) _converter = new Converter_Negative();
return _converter;
}
}
}
Использование преобразователя:
Определение пространства имен
Xmlns: преобразователи = "CLR-имена: MyProject.Converters; сборка = MyProject"
Пример использования этого конвертера в привязке
<RichTextBox IsReadOnly="{Binding Path=IsChecked, ElementName=toggleIsEnabled, Converter={converters:Converter_Negative}}"/>
Используйте IMultiValueConverter для передачи нескольких параметров команде
В качестве параметра CommandParameter
использовать несколько связанных значений с помощью MultiBinding
с очень простым IMultiValueConverter
:
namespace MyProject.Converters
{
public class Converter_MultipleCommandParameters : MarkupExtension, IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return values.ToArray();
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
private static Converter_MultipleCommandParameters _converter = null;
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (_converter == null) _converter = new Converter_MultipleCommandParameters();
return _converter;
}
public Converter_MultipleCommandParameters()
: base()
{
}
}
}
Использование преобразователя:
Пример реализации - метод, вызываемый при выполнении
SomeCommand
( примечание:DelegateCommand
- это реализацияICommand
которая не представлена в этом примере ):private ICommand _SomeCommand; public ICommand SomeCommand { get { return _SomeCommand ?? (_SomeCommand = new DelegateCommand(a => OnSomeCommand(a))); } } private void OnSomeCommand(object item) { object[] parameters = item as object[]; MessageBox.Show( string.Format("Execute command: {0}\nParameter 1: {1}\nParamter 2: {2}\nParamter 3: {3}", "SomeCommand", parameters[0], parameters[1], parameters[2])); }
Определение пространства имен
Xmlns: преобразователи = "CLR-имена: MyProject.Converters; сборка = MyProject"
Пример использования этого конвертера в привязке
<Button Width="150" Height="23" Content="Execute some command" Name="btnTestSomeCommand" Command="{Binding Path=SomeCommand}" > <Button.CommandParameter> <MultiBinding Converter="{converters:Converter_MultipleCommandParameters}"> <Binding RelativeSource="{RelativeSource Self}" Path="IsFocused"/> <Binding RelativeSource="{RelativeSource Self}" Path="Name"/> <Binding RelativeSource="{RelativeSource Self}" Path="ActualWidth"/> </MultiBinding> </Button.CommandParameter> </Button>