首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在MultiBinding中管理绑定的targetType

在MultiBinding中管理绑定的targetType
EN

Stack Overflow用户
提问于 2017-03-14 19:29:58
回答 3查看 1.2K关注 0票数 3

因此,我有一个多绑定与一个转换器,它接受一些值并找到它们的最大值。问题是其中一个绑定使用了期望double目标类型的转换器,而绑定具有object目标类型。我想知道是否有任何方法可以修改绑定的目标类型。

下面是我的xaml的近似值:

代码语言:javascript
复制
<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

代码语言:javascript
复制
<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

代码语言:javascript
复制
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中手动设置RequiresDoubleTargetConvertertargetType

EN

回答 3

Stack Overflow用户

发布于 2017-03-14 19:33:54

就类型系统而言,绑定在object上运行。如果你想要一个特定的类型,你需要确保你自己。

但是,您可以使用传递给转换器的目标类型来确定需要哪种类型,并相应地修改转换器的返回值。

票数 0
EN

Stack Overflow用户

发布于 2017-03-15 05:13:42

所以有没有办法手动设置转换器的目标类型,或者我坚持它是对象?

由于Convert方法的签名始终是相同的,即它只接受一个值的object[],所以您只能将其设置为object

您必须在Convert方法中将values[1]强制转换为double (因为该方法将始终且仅传递object类型的值):

代码语言:javascript
复制
double d = (double)values[1];
票数 0
EN

Stack Overflow用户

发布于 2018-09-07 01:31:24

我已经想出了一种绕过这个问题的方法,但只有当您有权访问您在MultiBinding本身上使用的转换器时,它才有效(或者您可以添加一个转换器)。如果它还使用ConverterParameter、TargetNullValue和/或StringFormat,还需要一些额外的工作。

诀窍在于,当您向MultiBinding添加子绑定时,您将从该子绑定中删除Converter、ConverterParameter、TargetNullValue和converter值,并将它们存储在多绑定转换器的Convert方法可以访问的位置。(我们使用包装器MarkupExtension来模拟MultiBinding,这样我们就可以在实际应用它们之前访问它们,因为一旦它们被应用,您就不能更改它们。)

然后,在多绑定的Convert方法中,您现在从子绑定中获得了原始的、尚未转换/格式化/合并的值,但您也有了所需的最终目标(在本例中为double),因为它被传递给您所在的MultiBinding的Convert方法。

有了这些信息,您就可以手动调用子转换器的Convert方法,传入尚未转换的值、targetType (传递给您)和childConverterParameter。

获取该调用的结果,如果为空,则返回子绑定中的TargetNullValue。

如果它不是null,并且两个targetType都是一个字符串,并且您有一个字符串格式,那么最后格式化结果。

这是伪代码(也就是我想不到的代码)。对于实际的代码,你可以看到我在我的StackOverflow here上的DynamicResourceBinding类中使用了它。)

代码语言:javascript
复制
// 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
}

同样,请查看链接以在上下文中查看它。

希望这能有所帮助!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42784793

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档