简体   繁体   中英

How to create DataSource dependency property on a wpf User Control

I have a user control that wraps a grid. I want to be able to set the underlying grid's data source, but through the user control, like this:

<my:CustomGrid DataSource="{Binding Path=CollectionView}" />

I have set this up in the grid like this:

    private static readonly DependencyProperty DataSourceProperty 
        = DependencyProperty.Register("DataSource", typeof(IEnumerable), typeof(CustomGrid));

    public IEnumerable DataSource
    {
        get { return (IEnumerable)GetValue(DataSourceProperty); }
        set
        {
            SetValue(DataSourceProperty, value);
            underlyingGrid.DataSource = value;
        }
    }

But this doesn't work (it doesn't give me an error either). The data source is never set. What am I missing?

When WPF loads your control and encounters a DependencyProperty specified in XAML, it uses DependencyObject.SetValue to set the property value and not your class's property. This makes custom code in property setters which are dependency properties pretty much useless.

What you should do is override the OnPropertyChanged method (from DependencyObject):

    protected override void OnPropertyChanged( DependencyPropertyChangedEventArgs e ) {
        base.OnPropertyChanged( e );

        if( e.Property == DataSourceProperty ) {
            underlyingGrid.DataSource = e.NewValue;
        }
    }

Alternately you can specify a callback when you register the DependencyProperty:

    public static readonly DependencyProperty DataSourceProperty =
        DependencyProperty.Register( "DataSource", typeof( IEnumerable ), typeof( MyGridControl ), new PropertyMetadata( DataSourceChanged ) );

And do effectively the same as above in OnPropertyChanged in the callback:

    public static void DataSourceChanged( DependencyObject element, DependencyPropertyChangedEventArgs e ) {
        MyGridControl c = (MyGridControl) element;
        c.underlyingGrid.DataSource = e.NewValue;
    }

this is OK:

  public static readonly DependencyProperty ItemsSourceProperty =
            DependencyProperty.Register("ItemsSource", typeof(IList), typeof(YourControl),
            newFrameworkPropertyMetadata(null,FrameworkPropertyMetadataOptions.AffectsArrange,new PropertyChangedCallback(OnIsChanged)));

 private static void OnIsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            YourControl c = (YourControl)d;
            c.OnPropertyChanged("ItemsSource");
        }

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

The problem was here: When you set

MyGridControl c = (MyGridControl) element;
c.underlyingGrid.DataSource = e.NewValue;

you set the value, but delete your binding!

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