tags:

views:

229

answers:

3

I have a UserControl called SharpComboBox. I am using MVVM model to populate the SharpComboBox with Categories. For that I need to set the ItemsSource property. Here is the usage of the SharpComboBox control.

  <sharpControls:SharpComboBox ItemsSource="{Binding Path=Categories}"  Grid.Column="1" Grid.Row="1" DisplayMemberPath="Title">   

            </sharpControls:SharpComboBox>

The Window is called the AddBook.xaml and here is the code behind:

 public AddBooks()
        {
            InitializeComponent();

            this.DataContext = new AddBookViewModel(); 

        }

And here is the implementation of the AddBookViewModel.

 public class AddBookViewModel
    {

        private CategoryRepository _categoryRepository; 

        public AddBookViewModel()
        {
            _categoryRepository = new CategoryRepository();
        }



        public List<Category> Categories
        {
            get
            {
                return _categoryRepository.GetAll(); 
            }
        }

And finally here is the SharpComboBox control:

<StackPanel Name="stackPanel">
        <ComboBox x:Name="comboBox">       

            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <ItemsControl>

                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"></ColumnDefinition>
                                <ColumnDefinition Width="2*"></ColumnDefinition>
                            </Grid.ColumnDefinitions>

                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"></RowDefinition>
                            </Grid.RowDefinitions>
                        </Grid>                                                

                         <TextBlock Grid.Column="0" Grid.Row="0" Text="{Binding Path=Title}" Margin="10" />
                         <Image Grid.Column="1" Margin="10" Grid.Row="0" Width="100" Height="100" Stretch="Fill" Source="{Binding Path=ImageUrl}">

                        </Image>                                                  


                    </ItemsControl>
                </DataTemplate>
            </ComboBox.ItemTemplate>


        </ComboBox>

    </StackPanel>

And here is the code behind:

public partial class SharpComboBox : UserControl
    {
        public static DependencyProperty ItemsSourceProperty; 

        public SharpComboBox()
        {
            InitializeComponent();
            this.DataContextChanged += new System.Windows.DependencyPropertyChangedEventHandler(SharpComboBox_DataContextChanged);


            ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof (IEnumerable),
                                                              typeof (SharpComboBox), null);

            comboBox.ItemsSource = ItemsSource; 
        }

        public IEnumerable ItemsSource
        {
            get { return (IEnumerable) GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }

        void SharpComboBox_DataContextChanged(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
        {

        }

For some reason the ItemsSource property is always null.

UPDATED:

void SharpComboBox_DataContextChanged(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
        {
            var binding = new Binding();
            binding.Source = this.DataContext;
            **binding.Path = new PropertyPath("Categories");**
            comboBox.SetBinding(ComboBox.ItemsSourceProperty, binding); 
        }
A: 

You cannot simply set the comboBox.ItemsSource from your property once in the constructor, who knows how early that happens. You need to set a binding between those two properties.

kek444
Can you give example or edit my code to reflect that?
azamsharp
I have updated the code but the ItemsSource which is my own dependency property always return null.
azamsharp
Got it code has been updated!
azamsharp
So is it working now?
kek444
Yes, it is working when I put "Categories" as the property Path. I am not using ItemsSource anymore since I need to provide a IEnumerable property name. I am using BoundCollectionName (string) property which simply is "Categories". Thanks!
azamsharp
+2  A: 

kek444 is very close, but there is one critical element missing. I've noticed your ViewModel doesn't implement INotifyPropertyChanged. This will prevent bindings from automatically refreshing when you've set that property. So, as kek444 mentioned, you are intially binding to null (because it's early) and then when you set it, you aren't informing your View of the change. It's pretty simple to change, though.

public class AddBookViewModel : INotifyPropertyChanged
{
    event PropertyChangedEventHandler PropertyChanged;
    public AddBookViewModel()
    {
         _categoryRepository = new CategoryRepository();
         if(PropertyChanged != null)
         {
              PropertyChanged(this, new PropertyChangedEventArgs("Categories");
         }
    }
    ...
}

Anytime you change your backing store (CategoryRepository), you'll want to do this. There may be some additional complication here depending on your your repository is implemented, but this information ought to at least explain what is going on.

As a practice, I generally create a base ViewModel class that implements INotifyPropertyChanged so I can add a few helper methods that wrap that PropertyChanged logic up... I just call OnPropertyChanged("MyProp"); and that's it.

One other thing that might help you is that bindings will report to the debug output if you configure them correctly: Debugging WPF Binding

Hope this helps.

Anderson Imes
A: 

Could you mail me sample code as to how you managed to get this to work

Kind Regards Garth [email protected]

Garth