1

I have an Interface and two classes.

public interface IFieldValue
{
  Int64 FieldId { get; set; }
  string Value { get; set; }
}

public class CarFieldValue : IFieldValue
{
  public Int64 CarId { get; set; }
  public Int64 FieldId { get; set; }
  public string Value { get; set; } 
}

public class HouseFieldValue : IFieldValue
{
  public Int64 HouseId { get; set; }
  public Int64 FieldId { get; set; }
  public string Value { get; set; } 
}

Now I have a generic usercontrol for displaying the field values of either Car or House. The usercontrol is bound to the according ViewModel.

public class CarViewModel : INotifyPropertyChanged
{
  (...)

  private ObservableCollection<CarFieldValue> _FieldValues;
  public ObservableCollection<CarFieldValue> FieldValues
  {
    get { return _FieldValues; }
    set
    {
      if (_FieldValues!= value)
      {
        _FieldValues= value;
        SendPropertyChanged("FieldValues");
      }
    }
  }
}

and

public class HouseViewModel : INotifyPropertyChanged
{
  (...)

  private ObservableCollection<HouseFieldValue> _FieldValues;
  public ObservableCollection<HouseFieldValue> FieldValues
  {
    get { return _FieldValues; }
    set
    {
      if (_FieldValues!= value)
      {
        _FieldValues= value;
        SendPropertyChanged("FieldValues");
      }
    }
  }
}

The usercontrol part looks like this:

public IReadOnlyList<IFieldValues> FieldValues
{
  get { return (IReadOnlyList<IFieldValues>)GetValue(FieldValuesProperty); }
  set { SetValue(FieldValuesProperty, value); }
}
public static readonly DependencyProperty FieldValuesProperty = DependencyProperty.Register("FieldValues", typeof(IReadOnlyList<IFieldValues>), typeof(FieldValuesControl), new UIPropertyMetadata(null));

The binding takes place in XAML in the Views, e.g. in the CarView:

<myCtrls:FieldValuesControl FieldValues="{Binding MyCarViewModel.FieldValues}" />

I found that solution here]1 and it works so far. But I need to edit (add or remove) items in the usercontrol. When I use an IList<IFieldValues> instead of IReadOnlyList<IFieldValues> the binding doesn't work. There are no binding errors/warnings.

I also tried ICollection<IFieldValues> without success. I could use IEnumerable<IFieldValues> as suggested in the comments but then I can't Add() items because I can't cast the IEnumerable.

How can I implement this scenario?

Update Since I didn't find a better solution I use ObservableCollection<IFieldValues> on both the ViewModels and the usercontrol. As my ViewModels doesn't do much with the Lists it's not to complicated. Thanks for your help.

Community
  • 1
  • 1
gumo
  • 645
  • 15
  • 35
  • Just a shot in the dark - have you tried specifying a OneWay binding? – LordWilmore Jul 12 '16 at 08:12
  • 1
    @LordWilmore OneWay doesn't help. – gumo Jul 12 '16 at 08:39
  • @Clemens: Yes, `IEnumerable does work, but I need to add/remove items in the usercontrol. I can`t cast the `IEnumerable` there to a `List` or `ObservableCollection`. Sorry, going to make that more clear in the question. – gumo Jul 12 '16 at 09:33
  • If you need to add items in the user control, you can't operate on a specialized list. However, you can hold a copy of the list items in a separate list of matching type. Something like `List items = srcList.Cast().ToList()` – grek40 Jul 12 '16 at 11:35

1 Answers1

0

Why you don't use a ObservableCollection or an IEnumerable in your UserControl?

Like other do:

And I think your problem is the same as here

Problem is in your DependencyProperty registration. Co-variance is not applicable for generic lists

Another possibility would be to use the ItemCollection class. The same is used from the default ItemsControl (see code).

Community
  • 1
  • 1
wake-0
  • 3,918
  • 5
  • 28
  • 45
  • Using an `ObservableCollection` leeds to binding errors because you can 't bind an explicit `ObservableCollection` respectively `ObservableCollection` to an generic `ObservableCollection`. `IEnumerable` and `IList` don't work too. Only `IReadOnlyList`. I haven't figured out the difference yet. – gumo Jul 12 '16 at 08:47
  • @gumo Have you tried `ObservableCollection`? – wake-0 Jul 12 '16 at 09:00
  • Using `object` has the same binding error as `ObservableCollection` "System.Windows.Data Error: 1 : Cannot create default converter to perform 'one-way' conversions between types 'ObservableCollection`1[CarFieldValue]' and 'ObservableCollection`1[Object]'. Consider using Converter property of Binding..." – gumo Jul 12 '16 at 09:14
  • @gumo the idea behind using means that the `ObservableCollection` from the `ViewModels` uses `object` too – wake-0 Jul 12 '16 at 09:19
  • Ah, OK, now I understand. I would like to avoid the then neccessary casting from object to `IFieldValues`. I will try `ItemCollection`. – gumo Jul 12 '16 at 09:34