简体   繁体   中英

How to Bind Listbox in WPF to a generic list?

i'm having trouble getting a clear answer for this. I have a Static class (DataHolder) that holds a static list with a complex type (CustomerName and CustomerID properties). I want to bind it to a ListBox in WPF but add another item that will have the word "All" for future drag and drop capablilities. Anyone?

Create a ViewModel Class you can databind to! The ViewModel can reference the static class and copy the items to its own collection and add the all item to it.

Like this

public class YourViewModel
{
        public virtual ObservableCollection<YourComplexType> YourCollection
        {
            get
            {
                var list = new ObservableCollection<YourComplexType>(YourStaticClass.YourList);
                var allEntity = new YourComplexType();

                allEntity.Name = "all";
                allEntity.Id = 0;

                list.Insert(0, allEntity);

                return list;
            }

        }
}

Note, sometimes, you need empty Items. Since WPF can't databind to null values you need to use the same approach to handle it. The empty business entity has been a best practice for it. Just google it.

That "All" item has to be part of the list you bind your ListBox against. Natuarally you can not add that item to the DataHolder list because it holds items of type Customer (or similar). You could of course add a "magic" Customer that always acts as the "All" item but that is for obvious reasons a serious case of design smell (it is a list of Customers after all).

What you could do, is to not bind against the DataHolder list directly but introduce a wrapper. This wrapper would be your ViewModel. You would bind your ListBox agains a list of CustomerListItemViewModel that represents either a Customer or the "All" item.

CustomerViewModel
{
    string Id { get; private set; }
    string Name { get; set; }
    public static readonly CustomerViewModel All { get; private set; }

    static CustomerViewModel()
    {
       // set up the one and only "All" item
       All = new CustomerViewModel();
       All.Name = ResourceStrings.All;
    }


    private CustomerViewModel()
    {
    }

    public CustomerViewModel(Customer actualCustomer)
    {
        this.Name = actualCustomer.Name;
        this.Id = actualCustomer.Id;
    }
}

someOtherViewModel.Customers = new ObservableCollection<CustomerViewModel>();
// add all the wrapping CustomerViewModel instances to the collection
someOtherViewModel.Customers.Add(CustomerViewModel.All);

And then in your Drag&Drop code somewhere in the ViewModel:

if(tragetCustomerViewModelItem = CustomerViewModel.All)
{
     // something was dropped to the "All" item
}

I might have just introduced you to the benefits of MVVM in WPF. It saves you a lot of hassle in the long run.

If you use binding than the data provided as the source has to hold all of the items, ie. you can't databind and then add another item to the list.

You should add the "All" item to the DataHolder collection, and handle the 'All' item separately in your code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM