2

I am trying to bind the results from a collection in my ViewModel to a combobox. Below is my code. Any help would be appreciated. If you need to see something else or need more information let me know.

XAML:

DataContext="clr-namespace:Alliance.Library.Email.EmailViewModel"

  <ComboBox x:Name="cboProviders" ItemsSource="{Binding Source=AddressProviders}" DisplayMemberPath="ProviderName" Grid.Row="0" Grid.Column="1"></ComboBox>

That is my combobox. I realize that the code for that is completely wrong, but I am new so I was trying to approach it with trial and error.

Code:

This is in my VeiwModel "EmailViewModel.cs":

 public IEnumerable<IEmailAddressesProvider> AddressProviders { get; set; }

This is my interface "IEmailAddressesProvider":

    public interface IEmailAddressesProvider
    {
        string ProviderName { get; }
        IEnumerable<EmailAddress> GetEmailUsers();
    }
}

Code for "EmailAddressProviders.cs" that contains GetEmailUsers():

[Export(typeof(IEmailAddressesProvider))]
    public class EmailAddressProvider : IEmailAddressesProvider
    {
        #region Private Properties

        private static readonly IEncryptionService encryptionService = AllianceApp.Container.GetExportedValue<IEncryptionService>();

        #endregion

        public string ProviderName
        {
            get { return "Alliance Users"; }
        }

        public IEnumerable<EmailAddress> GetEmailUsers()
        {
            IUserRepository userRepo = AllianceApp.Container.GetExportedValue<IUserRepository>();
            IEnumerable<User> users = userRepo.GetAllUsers().Where(a => a.IsDeleted == false).OrderBy(a => a.UserID).AsEnumerable();

            List<EmailAddress> AddressList = new List<EmailAddress>();

            foreach (var user in users)
            {
                if (user.DisplayName != null && user.EmailAddress != null && user.DisplayName != string.Empty && user.EmailAddress != string.Empty)
                    AddressList.Add(new EmailAddress() { DisplayName = encryptionService.DecryptString(user.DisplayName), Email = encryptionService.DecryptString(user.EmailAddress) });
            }

            AddressList.OrderBy(u => u.DisplayName);

            return AddressList;

        }
    }

I am using MEF so as to how these values are being set, I like to call 'magic.' I didn't write the email portion of this. I am just trying to take care of getting the elements in the combobox. Thanks again!

Mark Pearl
  • 7,573
  • 10
  • 47
  • 57
JLott
  • 1,818
  • 3
  • 35
  • 56
  • http://www.wintellect.com/cs/blogs/jlikness/archive/2010/06/10/tips-and-tricks-for-inotifypropertychanged.aspx – spender Feb 08 '13 at 14:51
  • 1. What exactly doesn't work? 2. Post how your StaticResource you're using for Binding is defined. – Haspemulator Feb 08 '13 at 14:51
  • It just doesn't contain the collection and I have not defined my StaticResource. Like I said, I am very new to this. I have found that it is not that intuitive. – JLott Feb 08 '13 at 14:52
  • It's been a while since I've done WPF, but doesn't that need to be an ObservableCollection, not an IEnumerable? – Corey Adler Feb 08 '13 at 14:53
  • 2
    @IronMan84 No. The advantage of an observable is simply that if the UI adds/removes/edits items the underlying collection is changed as well, and if the underlying collection is updated the UI is updated as well. If you use an `IEnumerable` it's a one time copy of the sequence to the Control. – Servy Feb 08 '13 at 14:54
  • Maybe this question will help - http://stackoverflow.com/questions/561166/binding-wpf-combobox-to-a-custom-list – Daniel Kelley Feb 08 '13 at 14:55
  • Also, using AddressProviders.ProviderName would be incorrect, since AddressProviders is a collection (and thus you can't just call ProviderName by itself). You might want to consider using a different public property whose Get is `AddressProviders.Select(ap => ap.ProviderName)` – Corey Adler Feb 08 '13 at 14:56
  • @Servy, thanks. Like I said, it's been a while since I've had to deal with WPF. :-) – Corey Adler Feb 08 '13 at 14:57
  • So is there not a simple way to just bind the whole collection haha. – JLott Feb 08 '13 at 14:57
  • Updating code to what I have now... It looks like it recognizes the collection, but there are not any values being shown. – JLott Feb 08 '13 at 17:18

2 Answers2

1

If you don't really have a StaticResource anywhere, you should not use it. For your situation, you most probably want to do the following:

Change GetEmailUsers() method to a property (you can only bind properties, not methods return values):

public interface IEmailAddressesProvider
{
    string ProviderName { get; }
    IEnumerable<EmailAddress> EmailUsers { get; set;};
}

Then change your XAML to this:

<ComboBox x:Name="cboProviders" ItemsSource="{Binding AddressProviders.EmailUsers}" Grid.Row="0" Grid.Column="1"></ComboBox>

Also make sure you set DataContext for your Page to your ViewModel instance.

EDIT: Okay, just understood that you're setting DataContext wrongly. Based on what you've written, you seem to set it somewhere in your XAML like this:

DataContext="clr-namespace:Alliance.Library.Email.EmailViewModel"

This essentially means you're setting your data context to a string, and then try to bind to that string's properties, which certainly don't exist. I'd recommend you to check your runtime output for a binding errors to make sure this is the case.

If that's really so, then you need to set DataContext correctly. The easiest option to begin with is to do this in your view's constructor:

public MyView()
{
    DataContext = new Alliance.Library.Email.EmailViewModel();
}
Haspemulator
  • 11,050
  • 9
  • 49
  • 76
  • I am going to post the code for what GetEmailUsers() to see if it changes the answer any. Thanks for helping! – JLott Feb 08 '13 at 15:10
  • I am wanting to display the provider name though and not the Email Users – JLott Feb 11 '13 at 14:49
1

I think this is what you want (in the View).

<ComboBox 
    x:Name="cboProviders" 
    ItemsSource="{Binding Source=AddressProviders}"
    DisplayMemberPath="ProviderName"
    Grid.Row="0" Grid.Column="1"></ComboBox>

DisplayMemberPath on MSDN.

Cameron MacFarland
  • 70,676
  • 20
  • 104
  • 133
  • I have implemented this, but it doesn't actually show the values in the ComboBox. It acts like something is there, but there is not actually any words. Do you know what could cause this? – JLott Feb 11 '13 at 15:04
  • That worked in my case. I needed to bind to a property of IEnumerable(A column of a table). I tried ItemsSource="{Binding Source=AddressProviders.ProviderName}" but didn't work, not sure why, but yours did. Thanks! – usefulBee Sep 30 '14 at 18:06