3

I'm trying to bind ObservableCollection of ValueTuples to ComboBox in WPF using Caliburn.Micro framework MVVM. When I do that in ViewModel:

private ObservableCollection<Tuple<string, string>> databasesFromDisk;
public ObservableCollection<Tuple<string, string>> DatabasesFromDisk
{
    get => databasesFromDisk;
    set
    {
        databasesFromDisk = value;
        NotifyOfPropertyChange(() => DatabasesFromDisk);
    }
}

and in XAML View:

<ComboBox x:Name="DatabasesFromDisk" DisplayMemberPath="Item1"/>

it works, ComboBox fills with first strings. But when I try to use C# 7 and change to:

private ObservableCollection<(string name, string path)> databasesFromDisk;
public ObservableCollection<(string name, string path)> DatabasesFromDisk
{
    get => databasesFromDisk;
    set
    {
        databasesFromDisk = value;
        NotifyOfPropertyChange(() => DatabasesFromDisk);
    }
}

it doesn't work when I don't change XAML - it shows empty list. It doesn't work when I change to DisplayMemberPath="name" - the same empty list. And it doesn't work properly when I remove DisplayMemberPath - it shows whole list but with both strings concatenated. How can I do it with ValueTuples?

Woo-Cash
  • 33
  • 8

1 Answers1

0

Before C# 7 all the Items of Tuple are properties which are bindable. In C# 7 ValueTuple are fields which are not bindable.

https://msdn.microsoft.com/en-us/library/dd386940(v=vs.110).aspx https://github.com/dotnet/corefx/blob/master/src/System.ValueTuple/src/System/ValueTuple/ValueTuple.cs#L291

One of the possible solution can be using the IValueConverter

public class ValueTupleConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var tuple = value as (string name, string path)?;

        if (tuple == null)
            return null;

        return tuple.Value.Name;
    }

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

<ComboBox x:Name="DatabasesFromDisk">
  <ComboBox.ItemTemplate>
    <DataTemplate>
      <TextBlock Text="{Binding Converter={StaticResource ValueTupleConverter}}"/>
    </DataTemplate>
  </ComboBox.ItemTemplate>
</ComboBox>

user2250152
  • 14,658
  • 4
  • 33
  • 57
  • Thanks. That clarifies it. So I guess I won't be using ValueTuples for binding. Your solution is good but it makes the code even more obscure than `Item1` and all I wanted is to make it clearer. – Woo-Cash Jul 27 '17 at 07:49