依赖属性WPF始终返回NULL

时间:2009-07-13 18:34:32

标签: wpf dependency-properties

我有一个名为SharpComboBox的UserControl。我正在使用MVVM模型用类别填充SharpComboBox。为此,我需要设置ItemsSource属性。以下是SharpComboBox控件的用法。

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

            </sharpControls:SharpComboBox>

Window被称为AddBook.xaml,这里是代码:

 public AddBooks()
        {
            InitializeComponent();

            this.DataContext = new AddBookViewModel(); 

        }

这是AddBookViewModel的实现。

 public class AddBookViewModel
    {

        private CategoryRepository _categoryRepository; 

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



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

最后这里是SharpComboBox控件:

<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>

这是背后的代码:

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)
        {

        }

由于某种原因,ItemsSource属性始终为null。

更新:

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); 
        } 

2 个答案:

答案 0 :(得分:2)

kek444非常接近,但缺少一个关键因素。我注意到你的ViewModel没有实现INotifyPropertyChanged。这样可以防止绑定在设置该属性时自动刷新。所以,正如kek444所提到的,你最初是绑定到null(因为它是早期的),然后当你设置它时,你没有通知你的View变化。不过,改变起来非常简单。

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

无论何时更改后备存储(CategoryRepository),您都希望这样做。这里可能会有一些额外的复杂功能,具体取决于您的存储库是否已实现,但这些信息至少应该解释发生了什么。

作为一种做法,我通常会创建一个实现INotifyPropertyChanged的基本ViewModel类,因此我可以添加一些帮助方法来包装PropertyChanged逻辑...我只是调用OnPropertyChanged(“MyProp”);就是这样。

另一件可能对您有帮助的事情是,如果您正确配置它们,绑定将报告给调试输出:Debugging WPF Binding

希望这有帮助。

答案 1 :(得分:0)

你不能简单地在构造函数中从属性中设置一次comboBox.ItemsSource,它知道发生的时间。您需要在这两个属性之间设置绑定。