1

I have two ComboBox on my code:

<ComboBox Name="comboBoxSelectCamera" ItemsSource="{Binding Path=ListCameras}" SelectionChanged="comboBoxSelectCamera_SelectionChanged" />
<ComboBox Name="comboBoxCities" ItemsSource="{Binding Path=ListCities}" />    

On my Window I have this code so the ComboBox understand where the Path comes from:

<Window ....
     DataContext="{Binding RelativeSource={RelativeSource Self}}"
     .... >

Both combos are binded to two listes that I created on my MainWindow:

public MainWindow()
{
    InitializeCitiesCombo();

    InitializeComponent();

    // Initialize the control that checks for cameras
    InitializeCameraControl();
    FillCameraProperties();
    DataContext = this;
}

The first ComboBox list is created before the InitializeComponent, so when its combo is created, it fills with the specific content.

The second ComboBox list is created after the InitializeComponent, because it depend on an object that loads the cameras, and, I don't know if that's the reason, but if the list is created after InitializeComponent, it doesn't fill the ComboBox.

I know there are other ways to fill a list of connected cameras on my computer, but I have to use that control that is created on the InitializeComponent and initiated on the InitializeCameraControl().

Any idea on how can I fill this ComboBox after the InitializeComponent?

EDIT: Declaration of both Lists:

private List<CameraInfo> ListCameras { get; set; } 
private List<String> ListCities { get; set; }

Somewhere in code, the ListCites:

ListCities = new List<String> { Madrid, Barcelona, Alicante, Valencia }

Somewhere in code, my control returns a list of the connected cameras (it works, it has elements but they don't display on the combo):

ListCameras = MyUserControl.ConnectedCameras;  // this returns a valid list of `CameraInfo`

My CameraInfo class:

public class CameraInfo
{
    public CameraInfo(string name, string id);

    public static implicit operator string(CameraInfo cameraInfo);

    public string Id { get; }
    public string Name { get; }

    public override string ToString();
}

Note that while we discuss this, I tried to change on the combo of cameras the DisplayMemberPath.

Binding error:

System.Windows.Data Error: 40 : BindingExpression path error: 'Text' property not found on 'object' ''MainWindow' (Name='')'. BindingExpression:Path=Text; DataItem='MainWindow' (Name=''); target element is 'TextBox' (Name=''); target property is 'Template' (type 'ControlTemplate')
Sonhja
  • 8,230
  • 20
  • 73
  • 131
  • What class are you using for your cameras list? Is it just List or ObservableCollection? – Blablablaster Apr 25 '13 at 08:25
  • Show us the declaration of the both lists. They aren't `ObservableCollections`, right? – DHN Apr 25 '13 at 08:26
  • What kind of list should they be? Note that the one that is created before the `InitializeComponent` is filling right, but the other one, not. – Sonhja Apr 25 '13 at 08:29

1 Answers1

2

Ok, there is your major problem. First, change your lists like this.

private ObservableCollection<CameraInfo> _listCamera; 
public ObservableCollection<CameraInfo> ListCameras
{
    get { return _listCamera ?? (_listCamera = new ObservableCollection<CameraInfo>()); }
}

I'm only showing it for one list, but you have to do it for both. To fill the list, don't reinstantiate them, but clear them. E.g.

private void FillCameraInfo()
{
    IEnumerable<CameraInfo> example = new[] { new CameraInfo(), new CameraInfo() };
    ListCameras.Clear();
    foreach(var exampleEntry in example)
        ListCameras.Add(exampleEntry);
}

It's only an example, so I kept it as simple as possible. If you would reinstantiate them the bindings would be 'destroyed'.

That the first ComboBox is filled correctly lies in the fact that you're filling it, before you initialize the components with their bindings. So the items can be found. The second ComboBox is not aware of the changes in ListCities, because it's not notified by it. If you use ObservableCollection<T> the ComboBox will be notified, please have a look here for more information. And the binding should work as expected.

Edit - Why you shouldn't reinstantiate the collections

If you would do the following to put the data into the collection

public FillCameraInfo()
{
    ListCameras = new ObservableCollection<CameraInfo>(someData); 
}

the bindings would still listen to the 'old' instance. But you changed the reference of ListCameras and nobody listens to the new instance.

Edit - Why you don't see anything

Ok, this is a bit odd, but it's like it is. The order of declartion of a ComboBox binding is pretty important, so that it works properly. Please have a look here for the right order.

Community
  • 1
  • 1
DHN
  • 4,807
  • 3
  • 31
  • 45
  • It still doesn't fill anything... :((( – Sonhja Apr 25 '13 at 08:45
  • Can you explain what do you mean when you say `if you would reinstantiate them, the bindings would be destroyed`?? – Sonhja Apr 25 '13 at 08:47
  • @Sonhja Oo - This is just an example. You can use what ever you want. I only wanted to demonstrate how you should fill the data in the collection. Nothing more... – DHN Apr 25 '13 at 08:47
  • Ok, do you get any binding errors? Is anything appearing in the `ComboBoxes`? Did you look with the debugger, what does the collections contain? – DHN Apr 25 '13 at 08:55
  • No binding errores, nothing appearing on `ComboBoxes`, the collection has the proper data, and I never reinstantiate it... – Sonhja Apr 25 '13 at 08:58
  • Oo - Are you a developer? *Doesn't work...* is not a proper error description. What's the **Debug Output** window of VS saying? Any binding errors? – DHN Apr 25 '13 at 09:13
  • Get calmed... of course I'm a developer, but I can't explain much more if my order is the correct... Sorry. – Sonhja Apr 25 '13 at 09:16
  • I'm calm. But you must admit *doesn't work* is not very helpful. ;o) Ok, then please show me your current state and don't touch anything meanwhile I've a look. ;o) Btw, I think the binding error comes from elsewhere. You should delete the line `DataContext = this` in your c_tor. From what I'm seeing, it could cause this issue, but I'm not sure about it. – DHN Apr 25 '13 at 09:20
  • Sure it's not so helpful... Ok, I erased the `DataContext = this` but I still have null `ComboBox`. But I still have a `BindingExpression path error...` (see last edit). Actually the same one. – Sonhja Apr 25 '13 at 09:25
  • Ok, solved! I introduced the `DisplayMemberValue` after erasing what you said last, and now it works. Thanks a lot, your answer was really helpful and instructive :o) – Sonhja Apr 25 '13 at 09:27
  • Puh...finally. xoD You're welcome. I already began to question me and my knowledge. One last tip. Get familiar with MVVM it's the best pattern to implement WPF/SL applications. – DHN Apr 25 '13 at 09:39
  • Hehe yes, finally! Thanks, I have some tutorials of MVVM, but I still didn't decide to start with. But I surely will do soon :o) – Sonhja Apr 25 '13 at 09:42