简体   繁体   中英

Bind to a Dependency Property that is in parent's DataContext

I would like to bind third column to a CollectionBindingTwo property that is within Window's DataContext and not inside DataContext of an Items from CollectionBindingOne .

By defining the second collection inside <DataGrid> WPF assumes local scope or something, and points to a property within Items of ItemsSource ( CollectionBindingOne ).

<DataGrid DockPanel.Dock="Top" ItemsSource="{Binding CollectionBindingOne}" AutoGenerateColumns="False">
    <DataGridTextColumn Header="One" Binding="{Binding PropOne}"/>
    <DataGridTextColumn  Header="Two" Binding="{Binding PropTwo}"/>
    <DataGridComboBoxColumn Header="Three" ItemsSource="{Binding CollectionBindingTwo}"/>
</DataGrid>

For example, this works because ComboBox is not inside a <DataGrid> :

<ComboBox IsEditable="True" ItemsSource="{Binding CollectionBindingTwo}"></ComboBox>

The DataGridComboBoxColumn is not a part of the Visual Tree so the usual RelativeSource/ElementName binding formats won't work. You can use a workaround by defining the ElementStyle and EditingStyle where those binding formats will work. Another option is to use a BindingProxy which I use for other spots and will save some XAML when there is no other reason to define an ElementStyle/EditingStyle.

This is the BindingProxy class which inherits from Freezable.

public class BindingProxy : Freezable
{
    #region Overrides of Freezable

    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }

    #endregion

    public object Data
    {
        get { return (object)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Data.
    // This enables animation, styling, binding, etc...
    public static readonly DependencyProperty DataProperty =
        DependencyProperty.Register("Data",
                                    typeof(object),
                                    typeof(BindingProxy),
                                    new UIPropertyMetadata(null));
}

Now your xaml looks like this:

<DataGrid DockPanel.Dock="Top"
          ItemsSource="{Binding CollectionBindingOne}"
          AutoGenerateColumns="False">
    <DataGrid.Resources>
        <helper:BindingProxy x:Key="proxy"
                             Data="{Binding }" />
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridTextColumn Header="One"
                            Binding="{Binding PropOne}" />
        <DataGridTextColumn Header="Two"
                            Binding="{Binding PropTwo}" />
        <DataGridComboBoxColumn Header="Three" 
                                ItemsSource="{Binding Data.CollectionBindingTwo,
                                              Source={StaticResource proxy}}" />
</DataGrid>

Don't forget to declare the helper namespace import at the top of your Window/UserControl.

That's what the [RelativeSource][1] bindings are for. In this case you should be able to target parent data context by way of the the DataGrid's data context:

<DataGrid>
    <DataGridComboBoxColumn Header="Three" ItemsSource="{Binding  
        RelativeSource={RelativeSource AncestorType=DataGrid},
        Path=DataContext.CollectionBindingTwo}" />
</DataGrid>

An ElementName binding should also work:

<DataGrid x:Name="dataGrid">
    <DataGridComboBoxColumn Header="Three" 
        ItemsSource="{Binding ElementName=dataGrid, Path=DataContext.CollectionBindingTwo}" />
</DataGrid>

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