views:

484

answers:

3

SOLVED SOLVED SLOVED

the generics list was a list of structs

if you use a class instead of a struct it works fine

i.e.

    public class Person
    {
        public string Name { get; set;}
        public string ID { get; set;}
    }
instead of


public struct Person
{
  public string Name;
  public string ID;
}

I am doing something wrong .. you know how it is.

I have tried playing around with ItemsSource , DataContext , DisplayMemberPath and SelectedValuePath and I either get a blank list of a list of the ToString method being called in the Person object;

WHAT WOULD REALLY HELP is for someone to publish an answer that works for this example.

I have simplified the problem as I am having difficulty in general with databinding generics.

I have created a simple Generic List of Person and want to bind it to a combo. (also want to try use a ListView too).

I either get a list of blanks or a list of 'xxxx.Person' where xxxx = namespace

       <Window x:Class="BindingGenerics.MainWindow"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                Title="MainWindow" Height="300" Width="300">
            <Grid>

                <ComboBox Name="ComboBox1"
                          ItemsSource="{Binding}"
                          Height="50"
                          DisplayMemberPath="Name"
                          SelectedValuePath="ID"
                          FontSize="14"
                          VerticalAlignment="Top">
                </ComboBox>

            </Grid>
        </Window>



using System.Windows;
using System.ComponentModel;

namespace BindingGenerics
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            Person p = new Person();
            // I have tried List and BindingList
            //List<Person> list = new List<Person>();
            BindingList<Person> list = new BindingList<Person>();

            p.Name = "aaaa";
            p.ID = "1111";
            list.Add(p);

            p = new Person();
            p.Name = "bbbb";
            p.ID = "2222";
            list.Add(p);

            p = new Person();
            p.Name = "cccc";
            p.ID = "3333";
            list.Add(p);

            p = new Person();
            p.Name = "dddd";
            p.ID = "4444";
            list.Add(p);

            ComboBox1.DataContext = list;
        }
    }

    public struct Person
    {
        public string Name;
        public string ID;
    }
}
A: 

In the code shown you're setting ItemsSource twice, the first time in XAML (called by InitializeComponent) to the DataContext of ComboBox1, which can't be determined from what you've posted but it's probably not what you want. After that you're resetting it from code to your list object (here with typos). In this code you're also adding the same instance of Person 4 times and just changing its Name and ID over and over. I suspect a combination of these issues and the fact that you're using a List instead of ObservableCollection are causing the issues in your application.

It would help narrow it down if you could post some actual code you're seeing problems with as what you've put here isn't even compilable.

John Bowen
I have put full code on here now
Adam
Please see modified question .. any help gratefully received.
Adam
A: 

Well... I'm assuming your actual code has corrected syntax, as the code you pasted in won't compile.

I put this code into a new WPF app and, after new-ing each Person object, my combobox populated fine. You might want to move your population code into a Loaded event, which will ensure the form is properly constructed. Here's the corrected xaml and codebehind (with a few syntax shortcuts):

xaml:

<Grid>
    <ComboBox Name="ComboBox1" Height="70"  
        DisplayMemberPath="Name"    
        SelectedValuePath="ID" />
</Grid>

codebehind:

    public Window1()
    {
        InitializeComponent();
        this.Loaded += new RoutedEventHandler(Window1_Loaded);
    }

    void Window1_Loaded(object sender, RoutedEventArgs e)
    {
        var list = new List<Person>();
        Person p = new Person(){Name = "aaaa",ID = "1111"};
        list.Add(p);
        p = new Person(){Name = "bbbb", ID="2222"};
        list.Add(p);
        p = new Person(){Name = "cccc", ID="3333"};
        list.Add(p);
        p = new Person(){Name = "dddd", ID="4444"};
        list.Add(p);
        ComboBox1.ItemsSource = list;
    }
David Makogon
yes .. an erro on my part .. whilst learning how to paste code on here .. still just calls the ToString() of Person rather than listing items
Adam
Did you follow the advice of itowlson above, and change your struct to a class, and fields to properties?While not necessary to have a class in your case, you must use a class if you ever want two-way binding, so it's good practice to use classes all the time.
David Makogon
+2  A: 

In your code sample, Person.Name is a field rather than a property. WPF data binding considers only properties, not fields, so you need to change Person.Name to be a property.

Change your Person declaration to:

public class Person
{
  public string Name { get; set; }
  public string ID { get; set; }
}

(For production code, you'll probably want to use an ObservableCollection<Person> rather than a List<Person> and either make Person immutable or make it implement INotifyPropertyChanged -- but those aren't the sources of your immediate problem.)

itowlson