WPF(通用转换器)
1.MathConverter
有时候我们想在XAML中对绑定的数据进行数值运算转换,就需要这个转换器了。
这个NuGet包可以使字符串进行数据运算。
using System;
using System.Globalization;
using System.Windows.Data;
using NCalc;
[ValueConversion(typeof(decimal), typeof(string))]
public class MathConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string expressionString = parameter as string;
expressionString = expressionString.Replace(" ", "");
expressionString = expressionString.Replace("@Value", value.ToString());
return new Expression(expressionString).Evaluate();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
<Window x:Class="WpfApp2.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp2"
mc:Ignorable="d"
Title="Window2" Height="450" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="50"/>
<RowDefinition Height="80"/>
</Grid.RowDefinitions>
<Grid.Resources>
<local:MathConverter x:Key="math"/>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="{TemplateBinding ActualWidth,Converter={StaticResource math},ConverterParameter=(@Value/2)}"
BorderBrush="Green" BorderThickness="2" Background="Brown">
<ContentPresenter Content="{TemplateBinding Content}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Button Content="Button"/>
<Button Content="Button" Grid.Row="1"/>
<Button Content="Button" Grid.Row="2"/>
</Grid>
</Window>
2.DateConverter
当我们将时间转换为字符串时,会根据需要选择时间格式或者要显示的时分秒,这时候就需要进行相应的转换了。
using System;
using System.Globalization;
using System.Windows.Data;
[ValueConversion(typeof(DateTime), typeof(string))]
public class DateConverter : IValueConverter
{
public string Format { get; set; } = "yyyy-MM-dd HH:mm:ss.fff";
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
DateTime dt = (DateTime)value;
return dt.ToString(Format);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return DateTime.Parse(value.ToString());
}
}
3.ImageConverter
通过该转换可以将字节数组转换为BitmapImage,可以直接在XAML中进行转换显示。
using System;
using System.Globalization;
using System.IO;
using System.Windows.Data;
using System.Windows.Media.Imaging;
[ValueConversion(typeof(BitmapImage), typeof(byte[]))]
public class ImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
BitmapImage bitmap = new BitmapImage();
byte[] barr = value as byte[];
bitmap.BeginInit();
bitmap.StreamSource = new MemoryStream(barr);
bitmap.EndInit();
bitmap.Freeze();
return bitmap;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
}
4.MultiValueConverter
在学习的时候有个苦恼,就是不能有一个自适应的圆,不能根据长宽自适应设置倒角。下面通过多绑定+数据转换设计一个自适应的Button。
using System;
using System.Globalization;
using System.Windows.Data;
[ValueConversion(typeof(double), typeof(double[]))]
public class RoundMathConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length != 2)
{
throw new NotImplementedException();
}
double d1 = (double)values[0];
double d2 = (double)values[1];
return Math.Min(d1, d2);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
[ValueConversion(typeof(System.Windows.CornerRadius), typeof(double[]))]
public class RoundRadiusConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length != 2)
{
throw new NotImplementedException();
}
double d1 = (double)values[0];
double d2 = (double)values[1];
return new System.Windows.CornerRadius(Math.Min(d1, d2));
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
<Window x:Class="WpfApp2.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp2"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="Window2" Width="800" Height="450" mc:Ignorable="d">
<Grid>
<Button Background="Brown" BorderBrush="Green" BorderThickness="2">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<Border.CornerRadius>
<MultiBinding>
<MultiBinding.Converter>
<local:RoundRadiusConverter />
</MultiBinding.Converter>
<Binding Path="ActualWidth" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
<Binding Path="ActualHeight" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
</MultiBinding>
</Border.CornerRadius>
<Border.Width>
<MultiBinding>
<MultiBinding.Converter>
<local:RoundMathConverter />
</MultiBinding.Converter>
<Binding Path="ActualWidth" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
<Binding Path="ActualHeight" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
</MultiBinding>
</Border.Width>
<Border.Height>
<MultiBinding>
<MultiBinding.Converter>
<local:RoundMathConverter />
</MultiBinding.Converter>
<Binding Path="ActualWidth" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
<Binding Path="ActualHeight" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
</MultiBinding>
</Border.Height>
</Border>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
</Window>