Search code examples
c#wpfmultibinding

How to set the sources in this multibinding example?


I have 2 classes like this:

public MyClass1: INotifyValueChanged
{
    public Dictionary<int, Color> Property1 
    { 
        public event PropertyChangedEventHandler PropertyChanged;

        get
        { 
             return this.property1
        }
        set
        {
             PropertyChanged.ChangeAndNotify(ref this.property1, value, () => Property1);
        }
    }
}

public MyClass2: INotifyValueChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public int Property2
    {   get
        { 
             return this.property2
        }
        set
        {
             PropertyChanged.ChangeAndNotify(ref this.property2, value, () => Property2);
        }
    }
}

ChangeAndNotify is an extension method I use instead of the normal syntax to notify a property changed bevause this way I dont need to type the name of the property being changed as a string, so I think it's not relevant for the problem. If need I'll post it.

I want to bind MyClass2.Property2 to an Rectangle.Fill.

To do this I have to create an IMultiValueConverter that will look for Property2 on the Dictionary of Property1 and return it's color.

In my XAML I created an entry to my converter class:

<local:MaterialConverter x:Key="MaterialsConverter" />

Then I tried to multibind the Rectangle:

<Rectangle>
    <Rectangle.Fill>
        <SolidColorBrush>
            <SolidColorBrush.Color>
                <MultiBinding Converter="{StaticResource MaterialsConverter}">
                    <Binding Path=Property1 />
                    <Binding Path=Property2 />
                </MultiBinding>
            </SolidColorBrush.Color>
        </SolidColorBrush>
     <Rectangle.Fill/>
</Rectangle>

On the form code I have 2 variables of these 2 classes: classObj1 and classObj2 respectively.

After initialise and setup them I do this to bind:

rectangle.DataContext = class1Obj;

Of course it doesn't work because it's a multibinding and I have specified only 1 element in DataContext and I got an error saying that Property2 does not exist on MyClass1.

I don't think I can set 2 DataContexts to an object, but I could somehow set the Source property of one of the 2 bindings in the XAML, so one binding would come from the DataContext of the rectangle and the other would come from this another place. But where could I put the class2Obj or how?


Solution

  • Here is an example that should help you. Let's start with 2 simple classes:

    public class A
    {
        public string Name { get; set; }
    }
    
    public class B
    {
        public Dictionary<string, string> Dict { get; set; }
    }
    

    Let's initialize DataContext in the following way:

    window.DataContext = new object[]
    {
        new A{ Name = "Hello!" }, 
        new B
        { 
            Dict =new Dictionary<string, string> { "1", "a"}, {"2", "b"} 
        }
    };
    

    Now let's create a converter. I assume that the first object in the values array is of type A and the second is of type B:

    public class MultiConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            var sb = new StringBuilder();
            sb.AppendLine(values[0].ToString());
            foreach (var kvp in (Dictionary<string, string>) values[1])
                sb.AppendLine(kvp.Key + "-" + kvp.Value);
            return sb.ToString();
        }
        //...
    }
    

    And finally here is XAML:

    <Window.Resources>
        <local:MultiConverter x:Key="converter"></local:MultiConverter>
    </Window.Resources>
    <TextBlock Name="textBox2">
        <TextBlock.Text>
            <MultiBinding Converter="{StaticResource converter}">
                <Binding Path="[0].Name"/>
                <Binding Path="[1].Dict"/>
            </MultiBinding>
        </TextBlock.Text>
    </TextBlock>