wpf 绑定转换器参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15309008/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 23:43:06  来源:igfitidea点击:

Binding ConverterParameter

wpfxamlstyles

提问by dotNET

Is there a way I could do this in a Style:

有没有办法我可以做到这一点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>

I simply need to send the Tagof top-level parent and the Tagof control itself to my converter class.

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

回答by Clemens

The ConverterParameterproperty can not be bound because it is not a dependency property.

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

Since Bindingis not derived from DependencyObjectnone of its properties can be dependency properties. As a consequence, a Binding can never be the target object of another Binding.

由于Binding不是派生自DependencyObject其任何属性都不能是依赖属性。因此,一个 Binding 永远不能成为另一个 Binding 的目标对象。

There is however an alternative solution. You could use a MultiBindingwith a multi-value converterinstead of a normal Binding:

然而,有一个替代解决方案。您可以将 aMultiBinding多值转换器一起使用,而不是普通的 Binding:

<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>

The multi-value converter gets an array of source values as input:

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

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

回答by sa_ddam213

No, unfortunately this will not be possible because ConverterParameteris not a DependencyPropertyso you won't be able to use bindings

不,不幸的是这是不可能的,因为ConverterParameter不是,DependencyProperty所以你将无法使用绑定

But perhaps you could cheat and use a MultiBindingwith IMultiValueConverterto pass in the 2 Tagproperties.

但也许你可以作弊并使用MultiBindingwithIMultiValueConverter来传递 2 个Tag属性。

回答by Pascalsz

There is also an alternative way to use MarkupExtension in order to use Binding for a Converter Parameter. With this Solution you can still use the default IValueConverter instead of the IMultiValueConverter because the ConverterParameter is passed into the IValueConverter just like you expected in your first sample.

还有一种使用 MarkupExtension 的替代方法,以便对转换器参数使用绑定。使用此解决方案,您仍然可以使用默认的 IValueConverter 而不是 IMultiValueConverter,因为 ConverterParameter 就像您在第一个示例中预期的那样传递到 IValueConverter。

Here is my reusable MarkupExtension:

这是我的可重用 MarkupExtension:

/// <summary>
///     <example>
///         <TextBox>
///             <TextBox.Text>
///                 <wpfAdditions:ConverterBindableParameter Binding="{Binding FirstName}"
///                     Converter="{StaticResource TestValueConverter}"
///                     ConverterParameterBinding="{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) };
        }
    }
}

With this Extension in your Codebase you can simply Bind the Converter Parameter the following way:

使用代码库中的此扩展,您可以通过以下方式简单地绑定转换器参数:

<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>

Wich looks almost like your initial proposal

看起来很像你最初的提议