Joy Hyuk Lee
Joy Hyuk Lee

Reputation: 776

WPF data binding with member variable of class

I have a class like this.

public class ViewModel
{
    public PengChat3ClientSock Sock { get; internal set; }

    public ObservableCollection<Room> Rooms { get; internal set; }

    public ViewModel(PengChat3ClientSock sock)
    {
        Sock = sock;
        Rooms = new ObservableCollection<Room>();
    }
}

and MainWindow.xaml.cs

public ObservableCollection<ViewModel> viewModel { get; set; }

(Of course it is initialized.)

And here is a constructor.

comboBox.ItemsSource = viewModel;

But here, i do not want to use viewModel, only viewModel.Sock.

How can i do this?

Upvotes: 0

Views: 1524

Answers (3)

sondergard
sondergard

Reputation: 3234

You can only bind an ItemsSource to a type which implements IEnumerable. I have run into this before, and made a converter to convert any object to a list. It's a simple and reusable solution, which leaves the ViewModel logic separated from the view logic:

Converter:

public class ItemToCollectionConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return new List<object> { value };
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

XAML

<UserControl.Resources>
    <local:ItemToCollectionConverter x:Key="ItemToCollectionConverter"/>
</UserControl.Resources>
...
<ComboBox ItemsSource="{Binding Sock, Converter={StaticResource ItemToCollectionConverter}}"/>

Upvotes: 0

t0yk4t
t0yk4t

Reputation: 892

Usually you would go about this in a slightly different way:

  1. Create View (UserControl with all the ui elements you need)
  2. Set your 'ViewModel' as DataContext on the newly created View (userControl.DataContext = viewModel)
  3. In the view, where you define your combobox, you can now refer directly to the 'Sock' property on your viewmodel via Bindings.

Code:

<ComboBox ItemsSource="{Binding Sock}"/>

If you just want to set the ItemsSource from code-behind, which is kind of ugly, you might simply add the items in Sock to comboBox.Items - Alternatively you may need to create a new 'Binding' object from code-behind, but this is even uglier:

var binding = new Binding("Sock")
{
    Source = viewModel
};
comboBox.ItemsSource = binding;

Please note that I haven't tested the 'Binding in code-behind approach', it's really an anti pattern to do it like that, especially if you're working with MVVM.

Also, you 'Sock' property is a class, and not a collection, so you won't really be able to do this; did you perhaps mean the 'Rooms' property of the ViewModel?

Upvotes: 0

Jogy
Jogy

Reputation: 2475

There is no viewModel.Sock, as viewModel is a collection of objects of type ViewModel, which contain that property.

Depending on your goals there are different solutions:

  • You can still bind comboBox to viewModel, but in the item template of the comboBox you can access the Sock property

  • You can create new collection that will contain only Sock objects ... but then you may have to make sure it is synchronized with the collection of ViewModel objects

Upvotes: 1

Related Questions