0
votes

I am having problem binding ObservableCollection as ItemsSource to a combo box (this combobox is in a listview of having some rows). I followed A collection of StackPanel as ItemsSource of ComboBox but I did not get any clues for resolving my problem.

Problem:

  1. I was able to add items to a combobox which is at the top on the form.
  2. I have created a listview containing 3 text blocks and 1 combobox.
  3. I am successful in populating data for the text blocks in listview.
  4. But the problem lies with Combobox. First time, it shows all the items for each row in ListView. Once I select item or click on the combobox again to see the items, my list disappears. Only one combobox in the listview row shows all items. Other comboboxes shows blank.

Also, I was trying to save the index of the selected item and show the selected panel next time. But I did not get how to bind the stackpanel with selecteditem and selecteditemvalue.

I tried many ways of directly binding the items to the combobox in listview. But nothing worked. Request someone to help me on this.

Details of the code is given below:

I have XAML like below:

<Grid>
    <Grid Height="40">
        <ComboBox x:Name="cbList" />
    </Grid>
    <Grid Margin="0,56,0,168"></Grid>
    <ListView x:Name="lvFirst" Margin="0,195,0,12">
        <ListView.View>
            <GridView >
                <GridViewColumn>
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Width="50" x:Uid="tbListView1" Text="{Binding FirstName}" />
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn>
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Width="50" x:Uid="tbListView2" Text="{Binding LastName}" />
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn>
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Width="50" x:Uid="tbListView1" Text="{Binding ID}" />
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn>
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox Width="100" x:Uid="cbListView" ItemsSource="{Binding Path=SPForComboBox}" />        
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>                        
                </GridViewColumn>
            </GridView>
        </ListView.View>
    </ListView>
</Grid>

In the code behind I have a Contact class as below:

public class Contact : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    void Notify(string propName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }

    private string _fn;
    private string _ln;

    public string FirstName
    {
        get
        { return _fn; }
        set
        { _fn = value; Notify("FirstName"); }
    }
    public string LastName
    {
        get
        { return _ln; }
        set
        { _ln = value; Notify("LastName"); }
    }

    private int _id;
    public int ID
    {
        get { return _id; }
        set { _id = value; Notify("ID"); }
    }

    public StackPanel sp;

    public override string ToString()
    {
        return FirstName + " " + LastName;
    }

    private ObservableCollection<StackPanel> _sp;
    public ObservableCollection<StackPanel> SPForComboBox
    {
        get { return _sp; }
        set { _sp = value; Notify("SPForComboBox"); }
    }
}

To populate cbList Items, I am repeatedly calling below function after Initialization() function:

private void AddColours(string name, byte hexcolor)
    {
        //Add this ShiftType to Combo box
        SolidColorBrush rectangleBrush = new SolidColorBrush();
        Color color = new Color();
        color.A = hexcolor;
        rectangleBrush.Color = color;

        System.Windows.Controls.StackPanel stkPanel = new StackPanel(); //stack panel to hold rectangle + text
        stkPanel.Orientation = Orientation.Horizontal;
        cbList.Items.Add(stkPanel);

        Rectangle colorRect = new Rectangle(); //rectangle showing colour for shift
        colorRect.Height = 12;
        colorRect.Width = colorRect.Height;
        colorRect.Fill = rectangleBrush;
        stkPanel.Children.Add(colorRect);

        System.Windows.Controls.TextBlock cboText = new TextBlock(); //Name of shift
        cboText.Text = name;
        cboText.Margin = new Thickness(5, 5, 5, 5);
        stkPanel.Children.Add(cboText);
    }

In the main window class, I have a created an ObservableCollection object as public static (object name is contacts).

public static ObservableCollection<Contact> contacts = new ObservableCollection<Contact>();

After the Initialization() function, I am populating contacts as below:

AddColours("First", 100);
        AddColours("Second", 50);
        AddColours("Third", 20);
        AddColours("Fourth", 0);
        AddColours("Fifth", 80);            

        Contact c1 = new Contact();
        c1.FirstName = "Digo";
        c1.LastName = "Maradona";
        c1.ID = 0;
        c1.SPForComboBox = new ObservableCollection<StackPanel>();
        foreach (StackPanel sp in cbList.Items)
        {
            c1.SPForComboBox.Add(sp);
        }

        Contact c2 = new Contact();
        c2.FirstName = "Brian";
        c2.LastName = "Lara";
        c2.ID = 1;
        c2.SPForComboBox = new ObservableCollection<StackPanel>();
        foreach (StackPanel sp in cbList.Items)
        {
            c2.SPForComboBox.Add(sp);
        }

        Contact c3 = new Contact();
        c3.FirstName = "Sachin";
        c3.LastName = "Tendulkar";
        c3.ID = 2;
        c3.SPForComboBox = new ObservableCollection<StackPanel>();
        foreach (StackPanel sp in cbList.Items)
        {
            c3.SPForComboBox.Add(sp);
        }

        contacts.Add(c1);
        contacts.Add(c2);
        contacts.Add(c3);

        lvFirst.ItemsSource = contacts;
1
since there can be only 1 parent to any child, and since SPForComboBox is contains UIElements i.e. StackPanel so that cause the issue, and only last combo shows the items. You may perhaps avoid using UIElements in the view model ie. the binding source, and use data templates to render the items.pushpraj
Hi, Thank you. But I can't use other methods as I need to change many places. I resolved the problem by creating each child again in foreach loop and added to SPForComboBox. Now the data is consistent and I can see them all the times. But the problem now is saving and retrieving the selected item in the combobox. I am able to select and save the item but when I am loading it, it is showing blank. I used SelectedValue={Binding Path=SP"} SelectedValuePath="ID" but nothing is showing up. Please let me know if I missed something. Thanks.SNR
I don't think that you need Notify("SPForComboBox") an observablecollection has build in notification.Core-One
I do not see any property named SP, are you missing something here? is it possible for you to post a working sample? may I try to fix in there.pushpraj
I find it very curious that you followed a totally WRONG question with a totally CORRECT answer, and used the code from the question rather than reading the answer.Federico Berasategui

1 Answers

0
votes

HighCore, Thank you very much for the links. I have existing implementation and adding combobox to that.

I too felt that the method followed is not good. I shall certainly look at the alternatives provided by you and suggested by pushpraj.

Answer: I thought referring objects in other combobox will work till the items exist in that combobox. But I need to create rectangle and textblock for reach combobox I am creating and for each entry in that combobox.

So certainly I need to do it in foreach loop. Also, once I do this I can use SelectedIndex referring to the integer and SelectedItem to sp (individual stackpanel in that class).

This method is not good to follow but might be helpful for somebody.

Thanks.