MultiConverter用法

时间:2012-05-17 14:56:50

标签: xaml data-binding datatrigger

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

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

请注意,我不相信多转换器是正确的方法,我发布了一个尝试solve this problem with DataTriggers here的类似问题。

我尝试使用MultiConverter实现(下面)有问题:

  1. 它与{Dependency.UnsetValue}崩溃,表明绑定错误
  2. 它可能会也可能不会返回正确的类型BitmapSource。它需要处理图像的两个源,可以是Gender,基于Resx的源或文件路径。我不知道如何检查错误的文件路径只是检查结果,因为没有抛出错误(我可以做一个File.Exists但似乎有点过分)。
  3. 代码暴露用于单元测试的事实并不像看起来那么有用,因为我不知道比较图像相等的简单而便宜的方法(参见下面的单元测试)。
  4. 如何开始清理此转换器代码和绑定?

    干杯,
    Berryl

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

0 个答案:

没有答案