4

I have a GridView with some columns displaying materials. The viewmodel values are all saved in kg, for some of the the view should convert and display them as liters. Which is easily done the one way using a IMultiValueConverter.

public object Convert(object[] values, ...){
    var valueInKg = (double)values[0];
    var density = (double)values[1];

    return valueInKg/density;
}

Now I have problems doing the backward conversion. I have tried to store the input values (density) in the converter, but do have a single instance of it and thus wrong density values sometimes. I found this x:shared="false" approach, but want to set the converter in a class derived from System.Windows.Data.MultiBinding.

public class MyBinding : MultiBinding {
    public MyBinding(){
        Converter = new MyConverter();
    }
}

I assumed this will result in a separate instance for each Binding - it does not. How can I achieve that?

EDIT: As suggested by mm8 in this answer the problem lies in the binding instance. When defining the binding on a GridViewColumn in its cell template I will hit the constructor only once per column. So the question is how can I change that - is it even possible?

Community
  • 1
  • 1
ChriPf
  • 2,700
  • 1
  • 23
  • 25
  • Just an idea. Maybe not using an IMultiValueConverter. Using a IValueConverter and giving the density as parameter should be working. The you can calculate liters from kg and kg from liters. – Mighty Badaboom Mar 13 '17 at 11:34
  • Do you want to create a single instance of the converter or not? – mm8 Mar 13 '17 at 11:38
  • No, I want separate converter instances. I however seems not the converter is the problem but rather the binding itself, although defined in the cell template. – ChriPf Mar 13 '17 at 12:00
  • Please refer to my answer for an example of how you could set up the binding in XAML then. – mm8 Mar 13 '17 at 12:42
  • @MightyBadaboom the parameter of an `IValueConverter` cannot be set using a binding unfortunately. – ChriPf Mar 13 '17 at 15:01
  • Ah, sry. It's not a DependencyProperty, forgot about that :/ – Mighty Badaboom Mar 13 '17 at 15:07

2 Answers2

0

I assumed this will result in a separate instance for each Binding - it does not.

The following certainly creates a new instance the MyConverter class:

Converter = new MyConverter();

Make sure that you are creating a new instance of the MyBinding class for each binding.

You could also create a new instance of the converter in XAML like this:

<TextBlock>
    <TextBlock.Text>
        <MultiBinding>
            <MultiBinding.Converter>
                <local:MyConverter />
            </MultiBinding.Converter>
            <Binding Path="Test" />
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>
mm8
  • 163,881
  • 10
  • 57
  • 88
0

Regarding keeping values in ConvertBack method: if I understood you correctly, you can use Binding.DoNothing in ConvertBack function. Example:

using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;

namespace Example.Converter
{
    public class StringFormatConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            // object[] values per index
            // 0 ... some value 1
            // 1 ... some value 2

            // ... do amazing stuff with values

            return "hello world";
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            try
            {
                // here: don't change source's "some value 1", and assign ToDecimal result to source's "some value 2"
                return new object[] {Binding.DoNothing, System.Convert.ToDecimal(value, culture) };
            }
            catch (Exception e)
            {
                // do not change anything in the source
                return new object[] {Binding.DoNothing, Binding.DoNothing};
            }
        }
    }
}
Anatoly Vasilyev
  • 336
  • 4
  • 17