tags:

views:

696

answers:

4

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?

+6  A: 

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;
    }
Adam Sills
+1 Another option (cleaner, IMHO) is to just bind from the XAML. ie. inside the UserControl where you declare the Grid, do something like <DataGrid ItemsSource="{Binding DataSource, ...}"/>
Kent Boogaart
A: 

Hi I am having the same problem, still does not work

Garth
You should add comments instead of posting answers that aren't answers.
Michael Hedgpeth
A: 

I have done same code as above but the thing is when my dataSource modify, but DataSourceChanged method doesn't fire..

please let me know how to resolve this thing.

Thanks, Parthiv.

Parthiv
A: 

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!

Olga