WPF:如何在 1 个绑定中使用 2 个转换器?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1594357/
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
WPF: how to use 2 converters in 1 binding?
提问by Natrium
I have a control that I want to show/hide, depending on the value of a boolean.
我有一个要显示/隐藏的控件,具体取决于布尔值。
I have a NegatedBooleanConverter (switches true to false and vice versa) and I need to run this converter first. I have a BooleanToVisibilityConverter and I need to run this converter after the NegatedBoolConverter.
我有一个 NegatedBooleanConverter(将 true 切换为 false,反之亦然),我需要先运行这个转换器。我有一个 BooleanToVisibilityConverter,我需要在 NegatedBoolConverter 之后运行这个转换器。
How can I fix this problem? I want to do this in XAML.
我该如何解决这个问题?我想在 XAML 中做到这一点。
edit: this is a possible solution.
编辑:这是一个可能的解决方案。
That doesn't seem to work. It first converts the value with the seperate converters and then does something with the converted values.
那似乎行不通。它首先使用单独的转换器转换值,然后对转换后的值执行某些操作。
What I need is:
我需要的是:
- Convert the value with the first converter (this gives convertedValue).
- Convert convertedValue with the second converter and it's this result that I need.
- 使用第一个转换器转换值(这给出了convertedValue)。
- 使用第二个转换器转换 ConvertValue,这就是我需要的结果。
采纳答案by Natrium
To answer my own question again: I have been using this solution for years now: http://www.codeproject.com/Articles/15061/Piping-Value-Converters-in-WPF
再次回答我自己的问题:我多年来一直在使用这个解决方案:http: //www.codeproject.com/Articles/15061/Piping-Value-Converters-in-WPF
It makes a new converter of 2 existing converters, calling the first one first, and then the second one etc etc.
它创建了一个由 2 个现有转换器组成的新转换器,首先调用第一个,然后调用第二个,依此类推。
I'm pretty pleased with this solution.
我对这个解决方案很满意。
回答by Natrium
This is what I did:
这就是我所做的:
public class CombiningConverter : IValueConverter
{
public IValueConverter Converter1 { get; set; }
public IValueConverter Converter2 { get; set; }
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
object convertedValue = Converter1.Convert(value, targetType, parameter, culture);
return Converter2.Convert(convertedValue, targetType, parameter, culture);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
and I call it like this:
我这样称呼它:
<converters:CombiningConverter x:Key="negatedBoolToVisibilityConverter" Converter1="{StaticResource NegatedBooleanConverter}" Converter2="{StaticResource BoolToVisibilityConverter}" />
A MultiValueConverter might also be possible I think. Maybe I'll try that later.
我认为 MultiValueConverter 也可能是可能的。也许我稍后会尝试。
回答by Jake Berger
Expanding on Natrium's great answer...
扩展 Natrium 的伟大答案......
XAML
XAML
<conv:ConverterChain x:Key="convBoolToInverseToVisibility">
<conv:BoolToInverseConverter />
<BooleanToVisibilityConverter />
</conv:ConverterChain>
Class
班级
/// <summary>Represents a chain of <see cref="IValueConverter"/>s to be executed in succession.</summary>
[ContentProperty("Converters")]
[ContentWrapper(typeof(ValueConverterCollection))]
public class ConverterChain : IValueConverter
{
private readonly ValueConverterCollection _converters= new ValueConverterCollection();
/// <summary>Gets the converters to execute.</summary>
public ValueConverterCollection Converters
{
get { return _converters; }
}
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return Converters
.Aggregate(value, (current, converter) => converter.Convert(current, targetType, parameter, culture));
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return Converters
.Reverse()
.Aggregate(value, (current, converter) => converter.Convert(current, targetType, parameter, culture));
}
#endregion
}
/// <summary>Represents a collection of <see cref="IValueConverter"/>s.</summary>
public sealed class ValueConverterCollection : Collection<IValueConverter> { }
回答by metao
In this case, you don't need a converter chain. You just need a configurable converter. This is similar to Carlo's answer above, but explicitly defines the true and false values (which means you can use the same converters for Hidden, Visible or Collapsed conversions).
在这种情况下,您不需要转换器链。您只需要一个可配置的转换器。这类似于上面 Carlo 的回答,但明确定义了 true 和 false 值(这意味着您可以对隐藏、可见或折叠转换使用相同的转换器)。
[ValueConversion(typeof(bool), typeof(Visibility))]
public class BoolToVisibilityConverter : IValueConverter
{
public Visibility TrueValue { get; set; }
public Visibility FalseValue { get; set; }
public BoolToVisibilityConverter()
{
// set defaults
FalseValue = Visibility.Hidden;
TrueValue = Visibility.Visible;
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (bool)value ? TrueValue : FalseValue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Then in XAML:
然后在 XAML 中:
<BoolToVisibilityConverter x:Key="BoolToVisibleConverter"
FalseValue="Hidden"
TrueValue="Visible" />
回答by Carlo
What we do in our project is make a regular BooleanToVisibilityConverter, said converter takes one parameter (anything at all, a string, an int, bool, whatever). If the parameter is set it inverts the result, if not, it spits out the regular result.
我们在我们的项目中做的是创建一个常规的 BooleanToVisibilityConverter,该转换器接受一个参数(任何东西,一个字符串,一个 int,bool 等等)。如果设置了参数,它会反转结果,如果没有,它会吐出常规结果。
public class BooleanToVisibilityConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
bool? isVisible = value as bool?;
if (parameter != null && isVisible.HasValue)
isVisible = !isVisible;
if (isVisible.HasValue && isVisible.Value == true)
return Visibility.Visible;
else
return Visibility.Collapsed;
}
public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new System.NotImplementedException();
}
#endregion
}
回答by Athanviel
Here is a combination of Natriumand metaoanswers to save you some time:
这是Natrium和metao答案的组合,可为您节省一些时间:
public class ComparisonConverter : IValueConverter
{
public object TrueValue { get; set; } = true;
public object FalseValue { get; set; } = false;
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value?.Equals(parameter) == true? TrueValue : FalseValue;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value?.Equals(TrueValue) == true ? parameter : Binding.DoNothing;
}
}
And how you use it:
以及如何使用它:
<converter:ComparisonConverter x:Key="ComparisonConverter" />
<converter:ComparisonConverter TrueValue="{x:Static Visibility.Visible}"
FalseValue="{x:Static Visibility.Collapsed}"
x:Key="ComparisonToVisibilityConverter" />
...
<RadioButton IsChecked="{Binding Type, ConverterParameter={x:Static entities:LimitType.MinMax}, Converter={StaticResource ComparisonConverter}}"/>
<TextBox Visibility="{Binding Type, ConverterParameter={x:Static entities:LimitType.MinMax}, Converter={StaticResource ComparisonToVisibilityConverter}}"/>
回答by Alan Mendelevich
I've just created what I've called ReversedBooleanToVisibilityConverter to basically do what those 2 would do for you but in one step.
我刚刚创建了我称之为 ReversedBooleanToVisibilityConverter 的东西,以基本上完成那些 2 将为您做的事情,但只需一步。
回答by John Myczek
To address this specific problem, instead of using two converters your could write your own BoolToVisibilityConverter that uses the ConverterParameter (as a bool) to determine whether or not to negate the original Boolean.
为了解决这个特定问题,您可以编写自己的 BoolToVisibilityConverter,而不是使用两个转换器,它使用 ConverterParameter(作为 bool)来确定是否否定原始布尔值。
回答by Alastair Pitts
Personally I would just make 1 single converter that does the full conversion. Unless you desperately need the converters (like the negation) in other places, it will be easier to maintain (imo) if the conversion is done once, in one place.
就我个人而言,我只会制作 1 个进行完全转换的转换器。除非您在其他地方迫切需要转换器(如否定),否则如果在一个地方完成一次转换,维护 (imo) 会更容易。
回答by Scott Lawrence
I think you may want to use a Multiconverter here instead of two separate converters. You should be able to reuse the logic from your existing converters. Check out this discussionfor a start.
我认为您可能想在这里使用 Multiconverter 而不是两个单独的转换器。您应该能够重用现有转换器的逻辑。看看这个讨论开始。