【问题标题】:Setting default value in XAML Multibinding StringFormat在 XAML Multibinding StringFormat 中设置默认值
【发布时间】:2017-11-06 17:28:01
【问题描述】:

我是 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 会查看 /Themes/Custom/Images/Controls/"Platform Name"/"Game Title".png

问题是,如果“游戏标题”.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();
    }
}
}

【问题讨论】:

    标签: wpf xaml string-formatting


    【解决方案1】:

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

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

    编辑
    在我们与 cmets 交谈之后,我建议您使用转换器,更准确地说是 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>
    

    【讨论】:

    • 那行不通,因为所有游戏都有标题,所有游戏都有平台。没有空值。我需要一种显示默认图像的方法,该默认图像仅在多重绑定实际上能够根据游戏标题找到图像时才被替换。
    • 啊,对不起。但是您说“问题是,如果“游戏标题”.png 存在,UI 只会显示图像。”。所以你的游戏可以有多个图像(多平台游戏),但总是至少有一个。所以你想要一些东西来检测可用图像的数量,如果有多个则选择默认?
    • 没有。目录结构为 /Themes/Custom/Images/Platform Name。在该文件夹中,您有 Platform Name.png(这将是默认图像)和每个具有不同控制器类型的游戏的一个图像。这些图像中的每一个都将被命名为与其要绑定的游戏相同的名称。 (例如,Super Mario.png、Kirby.png 等)。如果一个游戏没有归属于它的图像,例如,我有一个名为 Pacman 的游戏但没有 Pacman.png,我希望 UI 改为显示 Platform Name.png。
    • 所以空值位于 HDD 一侧,因此当您导航到 PacMan 游戏时,您需要获取 Platform Name.png。我建议在图像上使用转换器并删除该文本块。
    • 据我所知,您的转换器类不是公开的,这就是它无法创建它的原因。 WPF 将使用 relfection 来访问这些类,因此它们需要在外部可见。
    猜你喜欢
    • 2011-09-26
    • 2013-06-17
    • 2017-12-03
    • 1970-01-01
    • 2014-10-04
    • 1970-01-01
    • 2013-06-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多