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
Binding ConverterParameter
提问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 Tag
of top-level parent and the Tag
of control itself to my converter class.
我只需要将Tag
顶级父级的Tag
of 和控件本身发送到我的转换器类。
回答by Clemens
The ConverterParameter
property can not be bound because it is not a dependency property.
ConverterParameter
无法绑定该属性,因为它不是依赖属性。
Since Binding
is not derived from DependencyObject
none 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 MultiBinding
with 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 ConverterParameter
is not a DependencyProperty
so you won't be able to use bindings
不,不幸的是这是不可能的,因为ConverterParameter
不是,DependencyProperty
所以你将无法使用绑定
But perhaps you could cheat and use a MultiBinding
with IMultiValueConverter
to pass in the 2 Tag
properties.
但也许你可以作弊并使用MultiBinding
withIMultiValueConverter
来传递 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
看起来很像你最初的提议