所以,我有一个带有转换器的多绑定,它接受一些值并找到它们的最大值。问题是其中一个绑定使用的转换器需要double
目标类型,而绑定具有object
目标类型。我想知道是否有任何方法可以以任何方式修改绑定的目标类型。
以下是我的xaml的近似值:
<TextBlock>
<TextBlock.Width>
<MultiBinding Converter="{StaticResource _maxValueConverter}">
<Binding Source="{StaticResource _constantZeroValue}"/>
<Binding Path="ActualWidth"
ElementName="_previousTextBlock"
Converter="{StaticResource _requiresDoubleTargetConverter}"/>
</MultiBinding>
</TextBlock.Width>
</TextBlock>
所以基本上如果有任何方法可以告诉第二个绑定它输出的是双值,那就太棒了。
最小可验证完整示例:
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:WpfApplication1"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<StackPanel.Resources>
<sys:Double x:Key="constantZero">0</sys:Double>
<local:RequiresDoubleTargetConverter x:Key="requiresDoubleTargetConverter" />
<local:MaxValueConverter x:Key="maxValueConverter" />
</StackPanel.Resources>
<Border x:Name="topBorder"
BorderThickness="1"
BorderBrush="Black"
HorizontalAlignment="Left">
<TextBlock x:Name="topTextBlock"
Background="Aqua"
Text="{Binding TopText}" />
</Border>
<Border BorderThickness="1"
BorderBrush="Black"
MinWidth="100"
HorizontalAlignment="Left">
<TextBlock Background="ForestGreen"
Text="{Binding BottomText}"
TextWrapping="Wrap"
MinWidth="100">
<TextBlock.Width>
<MultiBinding Converter="{StaticResource maxValueConverter}">
<MultiBinding.Bindings>
<Binding Path="ActualWidth" ElementName="topTextBlock" Converter="{StaticResource requiresDoubleTargetConverter}" />
<Binding Source="{StaticResource constantZero}" />
</MultiBinding.Bindings>
</MultiBinding>
</TextBlock.Width>
</TextBlock>
</Border>
</StackPanel>
</Window>
MainWindow.xaml.cs
using System;
using System.Diagnostics;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public string TopText
{
get { return "Hello World!"; }
}
public string BottomText
{
get { return "hi earth."; }
}
public MainWindow()
{
InitializeComponent();
}
}
public class RequiresDoubleTargetConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// I am looking for a way to manually ensure that "targetType == typeof(double)" evaluates to true.
if (targetType != typeof(double))
{
return null;
}
else
{
// Actual converter performs this calculation.
return (double)value - 14;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
// Irrelevant method for our purposes.
throw new NotImplementedException();
}
}
public class MaxValueConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
double max = double.NegativeInfinity;
foreach (object value in values)
{
if (value is double)
{
max = Math.Max((double)value, max);
}
else
{
Debug.Fail("All values must be doubles");
}
}
return max;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
// Irrelevant method for our purposes.
throw new NotImplementedException();
}
}
}
这是使用Visual Studio 2015创建的,并经过验证可以显示错误行为。我要确定的是,是否可以从xaml手动设置targetType
的{{1}}。
答案 0 :(得分:0)
就类型系统而言,绑定在object
上运行。如果您想要特定类型,您需要确保自己。
但是,您可以使用传递给转换器的目标类型来确定所需的类型,并相应地修改转换器的返回值。
答案 1 :(得分:0)
那么有没有办法手动设置转换器的目标类型,还是我坚持认为它是对象?
由于object
方法的签名总是相同的,因此它会被Convert
所困扰,即它接受object[]
个值而不接受任何其他值。
您必须在values[1]
方法中将double
投射到Convert
(因为该方法将始终只传递object
类型的值):
double d = (double)values[1];
答案 2 :(得分:0)
我想出了一种解决方法,但是只有在您可以访问正在MultiBinding本身上使用的转换器(或者可以添加一个)的情况下,该方法才有效,如果有的话,还需要一些额外的工作还使用ConverterParameter,TargetNullValue和/或StringFormat。
技巧是,当您将子绑定添加到MultiBinding时,从该子绑定中删除Converter,ConverterParameter,TargetNullValue和StringFormat值,并将它们存储在MultiBinding转换器的Convert方法可访问的位置。 (我们使用包装器MarkupExtension来模拟MultiBinding,因此我们可以在实际应用之前访问所有内容,因为它们一经使用就无法更改。)
然后,在MultiBinding的Convert方法中,您现在从子绑定中获取原始的,尚未转换/格式化/合并的值,但您还拥有所需的最终目标(在此示例中为double)它已交给您所在的MultiBinding的Convert方法。
使用这些信息,然后您手动调用子转换器的Convert方法,传入尚未转换的值,targetType(传递给您)和childConverterParameter。
您获得该调用的结果,如果为null,则从子绑定中返回TargetNullValue。
如果它不为null,并且两个targetType都是一个字符串,并且您具有字符串格式,则最后格式化结果。
这是伪代码(即,浮出水面。大量语法错误等。对于实际代码,您可以看到我在StackOverflow {上的DynamicResourceBinding
类中使用它) {3}}。)
// Convert function for the MultiBinding
private object Convert(object[] values, Type targetType, object parameter, Culture culture){
var rawChildBindingResult = values[0]; // assuming it's in the first position
var convertedChildBindingResult = childConverter(rawChildBindingResult, targetType, childConverterParameter, culture);
if(convertedChildBindingResult == null)
convertedChildBindingResult = childTargetNullValue;
else if(targetType == typeof(string) && childStringFormat != null)
convertedChildBindingResult = string.Format(childStringFormat, convertedChildBindingResult);
// Now do whatever you would with the 'convertedChildBindingResult' as if things were normal
}
同样,请查看链接以在上下文中查看它。
希望这会有所帮助!