<MultiBinding Converter="{StaticResource JoinStringConverter}" ConverterParameter=" "> <Binding Path="FirstName" /> <Binding Path="MiddleName" /> <Binding Path="LastName" /> </MultiBinding>
public class JoinStringConverter : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { var separator = parameter as string ?? " "; return string.Join(separator, values); } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { var separator = parameter as string ?? " "; return (value as string)?.Split(new[] { separator }, StringSplitOptions.None).Cast<object>().ToArray(); } }
<MultiBinding Converter="{StaticResource JoinStringConverter}" ConverterParameter=" "> <Binding Path="MyProperty1" /> <MultiBinding Converter="{StaticResource JoinStringConverter}" ConverterParameter=", "> <Binding Path="MyProperty2" /> <Binding Path="MyProperty3" /> <Binding Path="MyProperty4" /> </MultiBinding> </MultiBinding>
[ContentProperty(nameof(Bindings))] public class NestedBinding : MarkupExtension { public NestedBinding() { Bindings = new Collection<BindingBase>(); } public Collection<BindingBase> Bindings { get; } public IMultiValueConverter Converter { get; set; } public object ConverterParameter { get; set; } public CultureInfo ConverterCulture { get; set; } public override object ProvideValue(IServiceProvider serviceProvider) { if (!Bindings.Any()) throw new ArgumentNullException(nameof(Bindings)); if (Converter == null) throw new ArgumentNullException(nameof(Converter)); var target = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget)); if (target.TargetObject is Collection<BindingBase>) { var binding = new Binding { Source = this }; return binding; } var multiBinding = new MultiBinding { Mode = BindingMode.OneWay }; var tree = GetNestedBindingsTree(this, multiBinding); var converter = new NestedBindingConverter(tree); multiBinding.Converter = converter; return multiBinding.ProvideValue(serviceProvider); } private static NestedBindingsTree GetNestedBindingsTree(NestedBinding nestedBinding, MultiBinding multiBinding) { var tree = new NestedBindingsTree { Converter = nestedBinding.Converter, ConverterParameter = nestedBinding.ConverterParameter, ConverterCulture = nestedBinding.ConverterCulture }; foreach (var bindingBase in nestedBinding.Bindings) { var binding = bindingBase as Binding; var childNestedBinding = binding?.Source as NestedBinding; if (childNestedBinding != null && binding.Converter == null) { tree.Nodes.Add(GetNestedBindingsTree(childNestedBinding, multiBinding)); continue; } tree.Nodes.Add(new NestedBindingNode(multiBinding.Bindings.Count)); multiBinding.Bindings.Add(bindingBase); } return tree; } }
public class NestedBindingNode { public NestedBindingNode(int index) { Index = index; } public int Index { get; } public override string ToString() { return Index.ToString(); } } public class NestedBindingsTree : NestedBindingNode { public NestedBindingsTree() : base(-1) { Nodes = new List<NestedBindingNode>(); } public IMultiValueConverter Converter { get; set; } public object ConverterParameter { get; set; } public CultureInfo ConverterCulture { get; set; } public List<NestedBindingNode> Nodes { get; private set; } }
public class NestedBindingConverter : IMultiValueConverter { public NestedBindingConverter(NestedBindingsTree tree) { Tree = tree; } private NestedBindingsTree Tree { get; } public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { var value = GetTreeValue(Tree, values, targetType, culture); return value; } private object GetTreeValue(NestedBindingsTree tree, object[] values, Type targetType, CultureInfo culture) { var objects = tree.Nodes.Select(x => x is NestedBindingsTree ? GetTreeValue((NestedBindingsTree)x, values, targetType, culture) : values[x.Index]).ToArray(); var value = tree.Converter.Convert(objects, targetType, tree.ConverterParameter, tree.ConverterCulture ?? culture); return value; } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
<TextBlock> <TextBlock.Text> <n:NestedBinding Converter="{StaticResource JoinStringConverter}" ConverterParameter=", "> <Binding Path="A" /> <n:NestedBinding Converter="{StaticResource JoinStringConverter}" ConverterParameter=" "> <Binding Path="B" /> <Binding Path="C" /> <n:NestedBinding Converter="{StaticResource JoinStringConverter}" ConverterParameter=""> <Binding Source="(" /> <Binding Path="D" /> <Binding Path="E" /> <Binding Source=")" /> </n:NestedBinding> </n:NestedBinding> <Binding Path="F" UpdateSourceTrigger="PropertyChanged" /> </n:NestedBinding> </TextBlock.Text> </TextBlock>
Source: https://habr.com/ru/post/277157/
All Articles