在XAML Multibinding StringFormat

时间:2017-11-06 17:28:01

标签: wpf xaml string-formatting

我是XAML的新手,我必须使用它来修改前端系统的UI。这些字段是固定的,我无法对其进行修改,因此我需要一个创造性的解决方案来解决我的问题,坦率地说,尽管我付出了最大的努力,但我还是没有足够的技巧。

UI用于显示数据库中视频游戏的属性。具体来说,我对目前允许显示视频游戏控制器图像的UI部分感兴趣(不同的游戏使用不同的控制器)。

按原样,UI仅允许为属于平台的每个视频游戏显示控制器,如下面的代码所示:

<TextBlock x:Name="PlatformControlPanel" Visibility="Collapsed">
    <TextBlock.Text>
         <MultiBinding StringFormat="{}pack://siteoforigin:,,,/Themes/Custom/Images/Controls/{0}/{0}.png">
             <Binding Path="SelectedGame.Platform" />
         </MultiBinding>
    </TextBlock.Text>
</TextBlock>
<Image Source="{Binding Text, ElementName=PlatformControlPanel}" RenderOptions.BitmapScalingMode="HighQuality" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="Uniform"/>

在上面的示例中,控制器图像以以下目录格式存储:/ Themes / Custom / Images / Controls /“Platform Name”/“Platform Name”.png

这很好用,但问题是给定的平台可以有多种控制器类型,如操纵杆控制器或GamePad控制器。

所以我想要做的是更改代码,使其显示给定平台的默认控制器,但为使用不同控制器类型的特定游戏显示不同的控制器。

要做到这一点,因为我无法在数据库中设置新字段,我修改了代码以根据游戏名称显示控制器:

<TextBlock x:Name="PlatformControlPanel" Visibility="Collapsed">
    <TextBlock.Text>
         <MultiBinding StringFormat="{}pack://siteoforigin:,,,/Themes/Custom/Images/Controls/{1}/{0}.png">
              <Binding Path="SelectedGame.Title" />
              <Binding Path="SelectedGame.Platform" />
         </MultiBinding>
     </TextBlock.Text>
</TextBlock>
<Image Source="{Binding Text, ElementName=PlatformControlPanel}" RenderOptions.BitmapScalingMode="HighQuality" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="Uniform"/>

此时,UI会查找/主题/自定义/图像/控件/“平台名称”/“游戏标题”.png

问题是,如果存在“Game Title”.png,则UI仅显示图像。否则,它什么也没有显示。

我不知道如何设置默认值,以便如果“平台名称”/“游戏标题”.png不存在,UI将回退到“平台名称”/“平台名称”.png。

有人可以帮助我吗?

修改 Xaml更新(省略了无关代码,构建时未报告错误):

<UserControl xmlns:converter="clr-namespace:BigBoxTheme.Views.Converters"

<!--Main Content Row-->
        <Grid Grid.Row="2">
            <Grid.Resources>
                <converter:MultiValueConverter x:Key="MultiValueConverter"/>
            </Grid.Resources>

<Image RenderOptions.BitmapScalingMode="HighQuality" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="Uniform">
                    <Image.Source>
                        <MultiBinding Converter="{StaticResource MultiValueConverter}">
                            <Binding Path="selectedExample"/>
                            <Binding Path="ValidationTest"/>
                        </MultiBinding>
                    </Image.Source>
                </Image>

C#代码:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows.Media.Imaging;

namespace BigBoxTheme.Views.Converters
{
class MultiValueConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        BitmapImage result = null;
        //process the variables passed in
        Uri SourceUri = new Uri($"pack://siteoforigin:,,,/Themes/Custom/Images/Controls/{values[1]}/{values[0]}.png", UriKind.Absolute);//use either string format or whatever you like to create a valid Uri
        if (File.Exists(SourceUri.AbsolutePath))
        {
            //we have found the image
            //no need to do anything just let it run through
        }
        else
        {
            //use the default
            SourceUri = new Uri($"pack://siteoforigin:,,,/Themes/Custom/Images/Controls/{values[1]}/{values[1]}.png", UriKind.Absolute);
        }
        return new BitmapImage(SourceUri);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
}

1 个答案:

答案 0 :(得分:1)

在您的绑定中使用TargetNullValue,如下所示:

<Binding Path="SelectedGame.Title" TargetNullValue="Platform Name" />  

修改
在我们的评论对话后,我建议您使用转换器,更准确地说是Multi Value Converter。它看起来像这样:

class MultiValueConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        BitmapImage result = null;
        //process the variables passed in
        Uri SourceUri = new Uri($"pack://siteoforigin:,,,/Themes/Custom/Images/Controls/{values[1]}/{values[0]}.png", UriKind.Absolute);//use either string format or whatever you like to create a valid Uri
        if (File.Exists(SourceUri.AbsolutePath))
        {
            //we have found the image
            //no need to do anything just let it run through
        }
        else
        {
             //use the default
             SourceUri = new Uri($"pack://siteoforigin:,,,/Themes/Custom/Images/Controls/{values[1]}/{values[1]}.png", UriKind.Absolute);
        }
        return new BitmapImage(SourceUri);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}  

然后你会像这样使用它:

<Image>
    <Image.Source>
        <MultiBinding Converter="{StaticResource MultiValueConverter}">
            <Binding Path="SelectedExample"/>
            <Binding Path="ValidationTest"/>
        </MultiBinding>
    </Image.Source>
</Image>  

编辑2
转换器位于自己的文件中,比如MultiValueConverter.cs,它会转到您的视图所在的位置,最好是在名为Converters的文件夹中。现在在顶部的xaml中你会包含这样的转换器:

xmlns:converter="clr-namespace:SO_app.Converters"//clr-namespace is the namespace of your view followed by a dot to access the Converters folder  

现在位于您的WindowUserControl资源标记内:

<Window.Resources>
    <converter:MultiValueConverter x:Key="MultiValueConverter"/>
</Window.Resources>