绑定到转换器参数

Posted

技术标签:

【中文标题】绑定到转换器参数【英文标题】:Binding to Converter Parameter 【发布时间】:2011-05-22 06:14:30 【问题描述】:

是否可以在 Silverlight 4.0 中绑定到 ConverterParameter?

例如,我想做这样的事情并将 ConverterParameter 绑定到 ViewModel 中的对象。

如果这不可能,还有其他选择吗?

<RadioButton
  Content="Binding Path=Mode"
  IsChecked="Binding
    Converter=StaticResource ParameterModeToBoolConverter,
    ConverterParameter=Binding Path=DataContext.SelectedMode,ElementName=root"
/>

【问题讨论】:

【参考方案1】:

可以通过创建自己的 Binding 来支持与 ConverterParameter 的绑定。使用方法如下:

<RadioButton Content="Binding Path=Mode" 
    IsChecked="BindingWithBindableConverterParameter Converter=StaticResource ParameterModeToBoolConverter,
    ConverterParameter=Binding Path=DataContext.SelectedMode,ElementName=root" />

以及实现此绑定的代码:

[ContentProperty(nameof(Binding))]
public class BindingWithBindableConverterParameter : MarkupExtension

    public Binding Binding  get; set; 
    public BindingMode Mode  get; set; 
    public IValueConverter Converter  get; set; 
    public Binding ConverterParameter  get; set; 

    public BindingWithBindableConverterParameter()
     

    public BindingWithBindableConverterParameter(string path)
    
        Binding = new Binding(path);
    

    public BindingWithBindableConverterParameter(Binding binding)
    
        Binding = binding;
    

    public override object ProvideValue(IServiceProvider serviceProvider)
    
        var multiBinding = new MultiBinding();
        Binding.Mode = Mode;
        multiBinding.Bindings.Add(Binding);
        if (ConverterParameter != null)
        
            ConverterParameter.Mode = BindingMode.OneWay;
            multiBinding.Bindings.Add(ConverterParameter);
        
        var adapter = new MultiValueConverterAdapter
        
            Converter = Converter
        ;
        multiBinding.Converter = adapter;
        return multiBinding.ProvideValue(serviceProvider);
    

    [ContentProperty(nameof(Converter))]
    private class MultiValueConverterAdapter : IMultiValueConverter
    
        public IValueConverter Converter  get; set; 

        private object lastParameter;

        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        
            if (Converter == null) return values[0]; // Required for VS design-time
            if (values.Length > 1) lastParameter = values[1];
            return Converter.Convert(values[0], targetType, lastParameter, culture);
        

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        
            if (Converter == null) return new object[]  value ; // Required for VS design-time

            return new object[]  Converter.ConvertBack(value, targetTypes[0], lastParameter, culture) ;
        
    

【讨论】:

【参考方案2】:

我找到了一个相关的 SO 帖子,我相信它可以回答这个问题:

WPF ValidationRule with dependency property

在我的具体示例中,我最终得到了 xaml,它在实现上述示例后看起来像这样:

<conv:BindingProxy x:Key="iconCacheHolder" Value="Binding ElementName=This,Path=IconCache" />
<conv:UriImageConverter  x:Key="ImageConverter">
    <conv:UriImageConverter.Proxy>
        <conv:IconCacheProxy Value="Binding Value, Source=StaticResource iconCacheHolder" />
    </conv:UriImageConverter.Proxy>
</conv:UriImageConverter>

【讨论】:

【参考方案3】:

我知道这是一个老问题,但也许这对遇到它的人有用。我找到的解决方案如下:

public class WattHoursConverter : FrameworkElement, IValueConverter
    

        #region Unit (DependencyProperty)

        /// <summary>
        /// A description of the property.
        /// </summary>
        public string Unit
        
            get  return (string)GetValue(UnitProperty); 
            set  SetValue(UnitProperty, value); 
        
        public static readonly DependencyProperty UnitProperty =
            DependencyProperty.Register("Unit", typeof(string), typeof(WattHoursConverter),
            new PropertyMetadata("", new PropertyChangedCallback(OnUnitChanged)));

        private static void OnUnitChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        
            ((WattHoursConverter)d).OnUnitChanged(e);
        

        protected virtual void OnUnitChanged(DependencyPropertyChangedEventArgs e)
        
        

        #endregion


        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        
// you can use the dependency property here
...


在你的 xaml 中:

<UserControl.Resources>
    <converters:WattHoursConverter x:Key="WattHoursConverter" Unit="Binding UnitPropFromDataContext"/>
 </UserControl.Resources>
....
  <TextBlock Grid.Column="1" TextWrapping="Wrap" Text="Binding TotalCO2, Converter=StaticResource KgToTonnesConverter" FontSize="13.333" />

【讨论】:

这看起来应该可以工作,但我得到了旧的“找不到目标元素的管理 FrameworkElement 或 FrameworkContentElement”、“DataItem=null”业务。 UnitPropFromDataContext 是您的视图模型的属性吗?如果绑定无论如何都没有 DataItem,那就没关系了。 这太可怕了,但它是唯一对我有用的东西:void View_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) (FindResource("ConverterKey") as ConverterType).PropertyName = (DataContext as ViewModelType)。视图模型属性; 【参考方案4】:

另一种选择是通过创建一个自定义转换器来包装您的其他转换器并从属性中传递转换器参数来获得幻想。这个自定义转换器只要继承DependencyObject,使用一个DependencyProperty,就可以绑定。例如:

<c:ConverterParamHelper ConverterParam="Binding ...">

    <c:ConverterParamHelper.Converter>

        <c:RealConverter/>

    </c:ConverterParamHelper.Converter>

</c:ConverterParamHelper>

【讨论】:

这种方法比使用 MultiBinding (switchonthecode.com/tutorials/wpf-tutorial-using-multibindings) 有优势吗? 你能发布一个实现吗? @Nathan 我想用这样的转换器实现ConvertBack 比使用MultiBinding 更容易。考虑一个TimeConverter,它将DateTime 转换为一个格式化的时间字符串。当使用MultiBinding 时,ConvertBack 只会得到格式化的字符串,这不足以解析整个DateTime。 Tim 的转换器也允许通过绑定到 ConvertBack 来传递日期。 @TimGreenfield 你能举个例子来说明如何使用它吗? 嗨蒂姆,我很想试试这个,但我需要比上面显示的更多的上下文和信息。您能否包括所有必要的部分来设置它? ConverterParamHelper 的源代码是什么样的? RealConverter 不仅存在,而且存在于包含绑定到的控件的元素的上下文中,等等。在半现实示例中显示更多上下文将非常有帮助,因为我似乎无法获得这种方法工作。【参考方案5】:

很遗憾,您不能绑定到 ConverterParameter。我过去使用过两个选项:不使用转换器,而是在您的 ViewModel(或您要绑定的任何东西)上创建一个属性来为您进行转换。如果您仍想走 Converter 路线,请将整个绑定对象传递给转换器,然后您可以通过这种方式进行计算。

【讨论】:

难道没有办法让转换器从DependencyObject 等继承吗?我正在创作一个自定义控件,我需要根据控件中的另一个属性来格式化绑定的对象。 “将整个绑定对象传递给转换器”是什么意思? 将对象传递给转换器,该转换器具有您进行转换所需的所有属性。在转换器中,将传入的对象转换为特定类型。 如果我将整个对象传递给转换器,我该如何实现ConvertBack?重新创建初始对象?只有当所有原始属性都作为value 传递给ConvertBack 时才有可能。 与@Clément 相同的问题,我想看看如何绑定整个绑定对象(在我的情况下为数据上下文)。

以上是关于绑定到转换器参数的主要内容,如果未能解决你的问题,请参考以下文章

阶段3 3.SpringMVC·_02.参数绑定及自定义类型转换_4 请求参数绑定集合类型

SpringMVC 从入门到精通系列 02——请求参数的绑定

使用一行语法中的参数绑定转换器

阶段3 3.SpringMVC·_02.参数绑定及自定义类型转换_2 请求参数绑定实体类型

spirng 数据绑定

WPF 中的选择性双命令绑定转换器?