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 を返す場合と返さない場合があります。画像の 2 つのソース (性別によって決定されるソース、Resx ベースのソース、またはファイル パスのいずれか) を処理する必要があります。エラーがスローされないため、結果を調べるだけで悪いファイルパスをキャッチする方法がわかりません(File.Existsを実行できますが、やり過ぎのようです)。
  3. コードが単体テスト用に公開されているという事実は、イメージの同等性を比較する簡単で安価な方法を知らないため、見かけほど有用ではありません (以下の単体テストを参照)。

このコンバーター コードとバインディングのクリーンアップを開始するにはどうすればよいですか?

乾杯、
ベリル

Converter.Convert コード

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;
}

BitmapHelper コード

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;
}

xaml バインディング

<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