绑定转换器参数

有没有办法我可以在 Style中做到这一点:

<Style TargetType="FrameworkElement">
<Setter Property="Visibility">
<Setter.Value>
<Binding Path="Tag"
RelativeSource="{RelativeSource AncestorType=UserControl}"
Converter="{StaticResource AccessLevelToVisibilityConverter}"
ConverterParameter="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Tag}" />
</Setter.Value>
</Setter>
</Style>

我只需要发送顶级父级的 Tag和控制本身的 Tag到我的转换器类。

176573 次浏览

不,不幸的是这是不可能的,因为 ConverterParameter不是 DependencyProperty,所以您不能使用绑定

但是也许您可以作弊,使用 MultiBindingIMultiValueConverter来传递2个 Tag属性。

无法绑定 ConverterParameter属性,因为它不是依赖项属性。

由于 Binding不是从 DependencyObject派生的,因此它的所有属性都不能是依赖属性。因此,Binding 永远不能成为另一个 Binding 的目标对象。

不过,还有另一种解决方案。你可以使用带有 多值转换器多值转换器MultiBinding,而不是普通的绑定:

<Style TargetType="FrameworkElement">
<Setter Property="Visibility">
<Setter.Value>
<MultiBinding Converter="{StaticResource AccessLevelToVisibilityConverter}">
<Binding Path="Tag" RelativeSource="{RelativeSource Mode=FindAncestor,
AncestorType=UserControl}"/>
<Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>

多值转换器获取一个源值数组作为输入:

public class AccessLevelToVisibilityConverter : IMultiValueConverter
{
public object Convert(
object[] values, Type targetType, object parameter, CultureInfo culture)
{
return values.All(v => (v is bool && (bool)v))
? Visibility.Visible
: Visibility.Hidden;
}


public object[] ConvertBack(
object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}

还有一种使用 MarkupExtension的替代方法,可以将 Binding用于 ConverterParameter。有了这个解决方案,您仍然可以使用默认的 IValueConverter而不是 IMultiValueConverter,因为 ConverterParameter被传递到 IValueConverter,就像您在第一个示例中期望的那样。

下面是我的可重复使用的 MarkupExtension:

/// <summary>
///     <example>
///         <TextBox>
///             <TextBox.Text>
///                 <wpfAdditions:ConverterBindableParameter Binding="{Binding FirstName}"
///                     Converter="{StaticResource TestValueConverter}"
///                     ConverterParameter="{Binding ConcatSign}" />
///             </TextBox.Text>
///         </TextBox>
///     </example>
/// </summary>
[ContentProperty(nameof(Binding))]
public class ConverterBindableParameter : MarkupExtension
{
#region Public Properties


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


#endregion


public ConverterBindableParameter()
{ }


public ConverterBindableParameter(string path)
{
Binding = new Binding(path);
}


public ConverterBindableParameter(Binding binding)
{
Binding = binding;
}


#region Overridden Methods


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);
}


#endregion


[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) };
}
}
}

有了这个代码库中的 MarkupExtension,你可以简单地通过以下方式绑定 ConverterParameter:

<Style TargetType="FrameworkElement">
<Setter Property="Visibility">
<Setter.Value>
<wpfAdditions:ConverterBindableParameter Binding="{Binding Tag, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}"
Converter="{StaticResource AccessLevelToVisibilityConverter}"
ConverterParameterBinding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Tag}" />
</Setter.Value>
</Setter>

看起来和你最初的提议差不多。