65.9K
CodeProject 正在变化。 阅读更多。
Home

WPF 中的自定义值转换

starIconstarIconstarIconemptyStarIconemptyStarIcon

3.00/5 (14投票s)

2012年7月9日

CPOL

2分钟阅读

viewsIcon

56272

downloadIcon

767

本文档描述了如何在 WPF 中执行自定义值转换。

引言

在 WPF 中,可以使用自定义值转换器将数据从一种类型转换为另一种类型。自定义转换器可用于实现自定义逻辑,将一个值转换为另一个值。为了演示本文,我使用 Visual C# 2010 Express Edition 开发了一个应用程序,该应用程序将十进制值作为输入,并将其转换为二进制、八进制和十六进制值。

背景

要创建自定义转换器,我们需要在用户定义的转换器类中实现 IValueConverter 接口。IValueConverter 接口有两个方法,我们必须在类中实现这些方法。这些方法如下:

  • Convert:此方法将源值转换为目标值。此方法的签名如下:
  • public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

    在此方法中,我们编写自定义转换的逻辑。

  • ConvertBack:此方法将值从目标转换回源值。此方法的签名与 Convert 方法相同。如果不想将值转换回源值,则可以避免在此方法中编写自定义代码。

Using the Code

以下 XAML 代码用于定义应用程序的用户界面:

<Window x:Class="NumberSystemConversion.MainWindow"        
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:NumberSystemConversion"
        Background="BlanchedAlmond"
        Title="Number System Converter" Height="350" Width="600">
    <Window.Resources>
        <local:NumberSystemConverter x:Key="myConverter"/>
    </Window.Resources>
    <Canvas>
        <Label Canvas.Left="100" Canvas.Top="10" FontFamily="Comic Sans MS" 
               FontSize="32" Foreground="Fuchsia">Number System Converter</Label>
        <Label Canvas.Left="40" Canvas.Top="100" FontFamily="Aharoni" FontSize="24" 
               Foreground="BlueViolet">Enter a Decimal Number: </Label>
        <TextBox Name="txtDecimal" Canvas.Left="330" Canvas.Top="100" Width="225" 
               FontFamily="Aharoni" FontSize="24" 
               Foreground="BlueViolet" Background="LightPink"/>
        <Label Canvas.Left="220" Canvas.Top="150" FontFamily="Lucida Console" 
               FontSize="24" Foreground="Red">Binary:</Label>
        <TextBlock Name="txtBinary" Canvas.Left="330" Canvas.Top="150" Width="225" 
               FontFamily="Lucida Console" FontSize="24" Foreground="Red" Background="LightPink"
               Text="{Binding ElementName=txtDecimal,Path=Text,Converter={StaticResource myConverter},ConverterParameter=2}"/>
        <Label Canvas.Left="233" Canvas.Top="200" FontFamily="Lucida Console" 
               FontSize="24" Foreground="Green">Octal:</Label>
        <TextBlock Name="txtOctal" Canvas.Left="330" Canvas.Top="200" Width="225" 
               FontFamily="Lucida Console" FontSize="24" Foreground="Green" Background="LightPink"
               Text="{Binding ElementName=txtDecimal,Path=Text,Converter={StaticResource myConverter},ConverterParameter=8}"/>
        <Label Canvas.Left="147" Canvas.Top="250" FontFamily="Lucida Console" 
               FontSize="24" Foreground="Blue">Hexadecimal:</Label>
        <TextBlock Name="txtHexadecimal" Canvas.Left="330" Canvas.Top="250" Width="225" 
               FontFamily="Lucida Console" FontSize="24" Foreground="Blue" Background="LightPink"
               Text="{Binding ElementName=txtDecimal,Path=Text,Converter={StaticResource myConverter},ConverterParameter=16}"/>
    </Canvas>
</Window>

在上面的代码中,我创建了一个名为 myConverter 的窗口资源,它指向我们的自定义转换器类 NumberSystemConverter。使用名为 txtDecimalTextBox 来接受要转换的数字。三个 TextBlocktxtBinarytxtOctaltxtHexadecimal 用于显示转换后的结果。这三个 TextBlock 使用元素绑定绑定到 txtDecimal TextBox。转换器 NumberSystemConverter 用于使用 Converter 属性将十进制数转换为二进制、八进制和十六进制。ConverterParameter 属性用于将目标类型指定为 2、8 和 16,分别用于转换为二进制、八进制和十六进制值。

以下是我们的数字系统转换器的代码:

public class NumberSystemConverter : IValueConverter
{
    Stack<object> stack = new Stack<object>();
    public object Convert(object value, Type targetType, object parameter, 
                  System.Globalization.CultureInfo culture)
    {
        // Store result digits in array
        object[] digits = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "A", "B", "C", "D", "E", "F" };
        try
        {
            // Get the source value
            int number = System.Convert.ToInt32(value.ToString());
            if (number == 0)
            {
                return 0;
            }
            // Get the target number system
            int divisor = System.Convert.ToInt32(parameter.ToString());
            while (number > 0)
            {
                int remainder = number % divisor;
                // Push digits to stack
                stack.Push(digits[remainder]);
                number /= divisor;
            }
            StringBuilder builder = new StringBuilder();
            while (stack.Count > 0)
            {
                builder.Append(stack.Pop().ToString());
                // Return digits in LIFO order
            }
            return builder.ToString();
            // Return result
        }
        catch (Exception)
        {
            return null;
        }
    }
    public object ConvertBack(object value, Type targetType, object parameter, 
                  System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

在上面的代码中,Convert 方法的第一个参数表示要转换的数字(number),第三个参数表示目标数字系统(divisor)。将数字除以除数,并将余数推入堆栈。最后,将数字从堆栈中弹出,并附加到 StringBuilder 对象。将 StringBuilder 转换为 String 并将其作为结果返回,以在目标 TextBlock 上显示。

不需要实现 ConvertBack 方法。

关注点

虽然转换器还有许多用途以及使用转换器的各种方法,但我希望上述讨论能帮助理解 WPF 中转换器的工作原理。

© . All rights reserved.