在 XAML Multibinding StringFormat 中设置默认值
Setting default value in XAML Multibinding StringFormat
我是 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
问题是,如果 "Game Title".png 存在,UI 只会显示图像。否则什么都不显示。
我不知道如何设置默认值,这样如果 "Platform Name"/"Game Title".png 不存在,UI 将回退到 "Platform Name"/"Platform Name".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();
}
}
}
在你的绑定中使用 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
现在在您的 Window
或 UserControl
资源标签内,如下所示:
<Window.Resources>
<converter:MultiValueConverter x:Key="MultiValueConverter"/>
</Window.Resources>
我是 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
问题是,如果 "Game Title".png 存在,UI 只会显示图像。否则什么都不显示。
我不知道如何设置默认值,这样如果 "Platform Name"/"Game Title".png 不存在,UI 将回退到 "Platform Name"/"Platform Name".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();
}
}
}
在你的绑定中使用 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
现在在您的 Window
或 UserControl
资源标签内,如下所示:
<Window.Resources>
<converter:MultiValueConverter x:Key="MultiValueConverter"/>
</Window.Resources>