0

这是我想使用多转换器实现的伪代码。

IF vm.AvatarFilePath IS NOT NULL THEN
    Image.Source = {Binding AvatarPath}
ELSE
    If vm.Gender == {x:Static vm:Gender.Female} THEN
        Image.Source = {StaticResource Img_Female}
    ELSE
        Image.Source = {StaticResource Img_Male}
    ENDIF
ENDIF

请注意,我不相信多转换器是正确的方法,我在此处发布了一个类似的问题,试图用 DataTriggers 解决这个问题

我对 MultiConverter 实现的尝试(如下)有问题:

  1. 它与 {Dependency.UnsetValue} 一起崩溃,这表明绑定是错误的
  2. 它可能会或可能不会返回正确的类型 BitmapSource。它需要处理图像的两个源,一个由 Gender 确定,一个基于 Resx 的源,或者一个文件路径。我不知道如何仅通过检查结果来捕获错误的文件路径,因为没有引发错误(我可以做一个 File.Exists 但似乎有点矫枉过正)。
  3. 为单元测试公开代码这一事实并不像看起来那么有用,因为我不知道有一种简单且便宜的方法来比较图像相等性(请参阅下面的单元测试)。

如何开始清理此转换器代码和绑定?

干杯,
贝里尔

Converter.转换代码

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
{
    values.ThrowIfNull("values");
    foreach (var value in values) {
        if (value != null && value.ToString().Equals("{DependencyProperty.UnsetValue}")) return Binding.DoNothing;
    }

    values[1].ThrowIfNull("gender (value[1])");

    var avatarPath = values[0] as string;
    BitmapSource result;

    if (string.IsNullOrWhiteSpace(avatarPath)) {
        var gender = (Gender) values[1];
        object bitmapSource;
        switch (gender)
        {
            case Gender.Female:
                bitmapSource = DomainSubjects.Img_Female;
                break;
            default:
                bitmapSource = DomainSubjects.Img_Male;
                break;
        }
        result = BitmapHelper.GetBitmapSource(bitmapSource);
    }
    else {
        var bi = new BitmapImage();
        bi.BeginInit();
        bi.UriSource = new Uri(avatarPath, UriKind.RelativeOrAbsolute);
        bi.EndInit();
        result = bi;
    }

    return result;
}

位图助手代码

public static BitmapSource GetBitmapSource(object source)
{
    BitmapSource bitmapSource = null;

    if (source is Icon)
    {
        var icon = source as Icon;

        // For icons we must create a new BitmapFrame from the icon data stream
        // The approach we use for bitmaps (below) doesn't work when setting the
        // Icon property of a window (although it will work for other Icons)
        //
        using (var iconStream = new MemoryStream())
        {
            icon.Save(iconStream);
            iconStream.Seek(0, SeekOrigin.Begin);
            bitmapSource = BitmapFrame.Create(iconStream);
        }
    }
    else if (source is Bitmap)
    {
        var bitmap = source as Bitmap;
        var bitmapHandle = bitmap.GetHbitmap();
        bitmapSource = Imaging
            .CreateBitmapSourceFromHBitmap(bitmapHandle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
        bitmapSource.Freeze();
        DeleteObject(bitmapHandle);
    }
    return bitmapSource;
}

xml绑定

<Image Grid.Column="1" Grid.Row="4" 
       HorizontalAlignment="Center" Margin="10, 0" Width="96" Height="96" Stretch="UniformToFill"
       >
    <Image.Source>
        <MultiBinding Converter="{StaticResource avatarPathConv}">
            <Binding Path="AvatarPath"/>
            <Binding Path="Gender"/>
        </MultiBinding>
    </Image.Source>
</Image>

无用的单元测试(加分!)

   [Test]
    public void Convert_AvatarPath_IfBadString_DefaultImage() {
        var conv = new AvatarPathConverter();
        var result = conv.Convert(new object[] {"blah", Gender.Male}, null, null, CultureInfo.InvariantCulture);
        Assert.That(result, Is.EqualTo(DomainSubjects.Img_Male));
    }
4

0 回答 0