gpt4 book ai didi

wpf - 嵌套绑定(bind)和管道转换

转载 作者:行者123 更新时间:2023-12-05 02:24:59 31 4
gpt4 key购买 nike

为了减少冗余的 XAML 标记,我尝试让一个单选按钮类型的选择控件被一般地填充,即我使用一个 ItemsControl 和一个枚举作为 ItemsSource 并创建一个 DataTemplate,它通过检查项目的枚举值是否与当前设置相同来显示选择了哪个项目。

这不能单独使用简单的转换器或 DataTrigger 完成,因为需要两个绑定(bind),所以我创建了一个通用的 MutliValueConverter 来检查相等性:

<CheckBox.Visibility>
<MultiBinding Converter="{StaticResource EqualityComparisonConv}">
<Binding Path="Key"/>
<Binding Path="DisplayMode_Current" Source="{x:Static local:App.Settings}"/>
</MultiBinding>
</CheckBox.Visibility>
public class EqualityComparisonConverter : IMultiValueConverter
{
#region IMultiValueConverter Members

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length < 2) throw new Exception("At least two inputs are needed for comparison");
bool output = (bool)values.Skip(1).Aggregate(values[0], (x1, x2) => { return x1.Equals(x2); });
return output;
}

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

#endregion
}

这里明显的问题是转换器返回一个 bool 值,我需要先将其转换为 Visibility

用转换器将 MultiBinding 包装在另一个绑定(bind)中是行不通的,因为这些属性不是依赖属性(因此不能为它们分配绑定(bind))。我可以想到一些解决方法,比如将 bool 存储在某些 Tag 属性中,这样我就可以将其用作新的绑定(bind)源,但我对这样的事情更感兴趣:

<CheckBox.Visibility>
<local:PipeConverter Converter="{StaticResource BooleanToVisibilityConv}">
<MultiBinding Converter="{StaticResource EqualityComparisonConv}">
<Binding Path="Key"/>
<Binding Path="DisplayMode_Current" Source="{x:Static local:App.Settings}"/>
</MultiBinding>
</local:PipeConverter>
</CheckBox.Visibility>

当原始绑定(bind)发生变化时,此类需要更新其输出,并且需要能够将其输出值公开给 Visibility 属性,但我不知道如何实现.遇到的一个问题是需要依赖属性,因此从 DependencyObject 继承会很好,但是从 Binding 类继承也很有意义,因为 PipeConverter 应该绑定(bind)并且需要设置为另一个依赖属性的值。

最佳答案

基于这样的想法(参见 publicgk's answeroption C),可以创建一个转换器,其中包含一组内部按顺序使用的转换器,我编写了一个符合我需要的劣质实现。即我可以在开始时使用 MultiValueConverter 并将输出通过管道传输到普通转换器列表中:

[ContentProperty("Converters")]
public class GroupConverter : IValueConverter, IMultiValueConverter
{
private IMultiValueConverter _multiValueConverter;
public IMultiValueConverter MultiValueConverter
{
get { return _multiValueConverter; }
set { _multiValueConverter = value; }
}

private List<IValueConverter> _converters = new List<IValueConverter>();
public List<IValueConverter> Converters
{
get { return _converters; }
set { _converters = value; }
}

#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return GroupConvert(value, Converters);
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return GroupConvertBack(value, Converters.ToArray().Reverse());
}

private static object GroupConvert(object value, IEnumerable<IValueConverter> converters)
{
return converters.Aggregate(value, (acc, conv) => { return conv.Convert(acc, typeof(object), null, null); });
}

private static object GroupConvertBack(object value, IEnumerable<IValueConverter> converters)
{
return converters.Aggregate(value, (acc, conv) => { return conv.ConvertBack(acc, typeof(object), null, null); });
}
#endregion

#region IMultiValueConverter Members
private InvalidOperationException _multiValueConverterUnsetException =
new InvalidOperationException("To use the converter as a MultiValueConverter the MultiValueConverter property needs to be set.");

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (MultiValueConverter == null) throw _multiValueConverterUnsetException;
var firstConvertedValue = MultiValueConverter.Convert(values, targetType, parameter, culture);
return GroupConvert(firstConvertedValue, Converters);
}

public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
if (MultiValueConverter == null) throw _multiValueConverterUnsetException;
var tailConverted = GroupConvertBack(value, Converters.ToArray().Reverse());
return MultiValueConverter.ConvertBack(tailConverted, targetTypes, parameter, culture);
}

#endregion
}

(如您所见,我几乎完全忽略了 ConverterParametersTargetTypesCultureInfo 参数,进一步 ConvertBack 方法未经测试,因此我不建议任何人实际使用它。)

XAML 用法:

<vc:GroupConverter MultiValueConverter="{StaticResource EqualityComparisonConv}">
<StaticResource ResourceKey="BoolToVisibilityConv"/>
</vc:GroupConverter>

关于wpf - 嵌套绑定(bind)和管道转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5524885/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com