0

I'm trying to pass in an array of system:Object to my converter as a parameter: Xaml: Doesn't work

<TextBlock.Text>
    <Binding ElementName="MainGrid" Path="DataContext"  Converter="{StaticResource TestConverter}">
        <Binding.ConverterParameter>
            <x:Array Type="system:Object">
                <Binding ElementName="MainGrid" Path="DataContext" />
                <Binding ElementName="SomeOtherElement" Path="DataContext" />
            </x:Array>
        </Binding.ConverterParameter>
    </Binding>
</TextBlock.Text>

Following XAML Does work, I found a sample online that used an array of Brush:

<TextBlock.Text>
    <Binding ElementName="MainGrid" Path="DataContext"  Converter="{StaticResource TestConverter}">
        <Binding.ConverterParameter>
            <x:Array Type="Brush">
                <SolidColorBrush Color="LawnGreen"/>
                <SolidColorBrush Color="LightSkyBlue"/>
                <SolidColorBrush Color="LightCoral"/>
            </x:Array>
        </Binding.ConverterParameter>
    </Binding>
</TextBlock.Text>

I get a System.Windows.Markup.XamlParseException: A 'Binding' cannot be used within a 'ArrayList' collection. A 'Binding' can only be set on a DepedencyProperty or a DependencyObject.

I've tried one of the suggested answers e.g. adding the ViewModel as a Dependency Object to my converter but that isn't working

public class TestConverter : DependencyObject , IValueConverter  
{
    public static readonly DependencyProperty PropertyTypeProperty = DependencyProperty.Register(
        "PropertyType", typeof (DerivedRacingViewModel), typeof (TestConverter), new PropertyMetadata(default(DerivedRacingViewModel)));

    public DerivedRacingViewModel PropertyType
    {
        get { return (DerivedRacingViewModel) GetValue(PropertyTypeProperty); }
        set { SetValue(PropertyTypeProperty, value); }
    }


    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var x = parameter;
        return "Test";
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var x = parameter;
        var z = parameter;
        throw new NotImplementedException();
    }
}

Then changing my xaml to:

<converters:TestConverter x:Key="TestConverter"  DerivedRacingViewModel="{Binding}" />

That give me compile time errors: 'DerivedRacingViewModel' was not found in type 'TestConverter'.

The reason behind doing this is I want to have 2 or 3 objects available when I'm doing my ConvertBack, e.g. I need the text that is entered into text box, the value that text box is bound to and the view model. This is where I'm having real difficulty. I've seen other people doing it by splitting strings and stuff but I really don't like that.

Cœur
  • 37,241
  • 25
  • 195
  • 267
DermFrench
  • 3,968
  • 13
  • 43
  • 70
  • Not sure how it does not work? You cannot get the array of Bindings in `parameter` argument? Are there any exceptions or errors (notified in ***Output*** window)? Note that `Binding` in XAML has a very complex implementation. – King King Oct 30 '14 at 17:36
  • that exception means you cannot use `Binding` like that. As I said, it's very complex, not some kind of normal instance. I suggest instead of creating Binding instance that way, you should try passing only the `ElementName` and `Path` (all of these are just strings), then in codebehind, you can try creating the `Binding` instances based on those inputs. – King King Oct 30 '14 at 17:40
  • 1
    that property is of course not found, it's just a Type, the right property is `PropertyType` – King King Oct 30 '14 at 18:08
  • D'oh I'm being really stupid, was using resharper and didn't complete, really tired been struggling with this. – DermFrench Oct 30 '14 at 18:09
  • feel easy, I'm being interested in this topic, just try and test it, if it's helpful I'll vote up:) – King King Oct 30 '14 at 18:10
  • Looks like what you want is an `IMultiValueConverter`, which allows you to provide several bound values as inputs to a `MultiBinding`, and produce a single result. – Mike Strobel Oct 30 '14 at 21:03
  • @MikeStrobel problem with MultiBinding for this approach is convert back as it only takes a single parameter. – DermFrench Oct 31 '14 at 21:51
  • @DermFrench Your `Binding` is on a read-only `TextBlock`. The binding only needs to be one-way, so why is that a problem? Just have `ConvertBack` throw a `NotSupportedException`. – Mike Strobel Nov 03 '14 at 00:41

1 Answers1

1

You should use an ItemsControl like below :

<TextBlock.Text>
    <Binding ElementName="MainGrid" Path="DataContext"  Converter="{StaticResource TestConverter}">
        <Binding.ConverterParameter>
               <ItemsControl>
                  <ItemsControl.Items>
                     <Label Content="{Binding ElementName=MainGrid, Path=DataContext}"/>
                     <Label Content="{Binding ElementName=SomeOtherElement, Path=DataContext}"/>
                  </ItemsControl.Items>
               </ItemsControl>
        </Binding.ConverterParameter>
    </Binding>
</TextBlock.Text>

TestConverter

public class TestConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        ItemsControl ctrl = parameter as ItemsControl;
        Label lbl = ctrl.Items[0] as Label;
        var c = lbl.Content;

        ...
    }
AnjumSKhan
  • 9,647
  • 1
  • 26
  • 38