Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bind to a parent/sibling of current datacontext/source property in WPF

How do we bind to a parent/sibling of a current datacontext (i.e. the source property representing the current datacontext)?

I am not talking about binding to the parent control's property (that case involves parent of target and not of source) - and that can be easily done by using RelativeSourceMode=FindAncestor.

RelativeSourceMode=PreviousData provides a limited support of binding to the previous sibling of the data item, but not to parent or other siblings.

Dummy Example:
(assume INPC in place)
How to bind ItemsSource of ComboBox to the Departments property of ViewModel?

public class Person
{
    public string Name { get; set; }
    public string Department { get; set; }
}

public class PersonViewModel
{
    public List<Person> Persons { get; set; }
    public List<string> Departments { get; set; }

    public PersonViewModel()
    {
        Departments = new List<string>();
        Departments.Add("Finance");
        Departments.Add("HR");
        Departments.Add("Marketing");
        Departments.Add("Operations");

        Persons = new List<Person>();
        Persons.Add(new Person() { Name = "First", Department = "HR" });
        Persons.Add(new Person() { Name = "Second", Department = "Marketing" });
        Persons.Add(new Person() { Name = "Third", Department = "Marketing" });
    }
}

XAML:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="300" Width="300">
    <Grid>
        <DataGrid ItemsSource="{Binding Persons}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox ItemsSource="{Binding Departments???}"
                                      SelectedValue="{Binding Department}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>
like image 943
publicgk Avatar asked Apr 23 '11 14:04

publicgk


People also ask

What is binding source in WPF?

A binding source is usually a property on an object so you need to provide both the data source object and the data source property in your binding XAML. In the above example the ElementName attribute signifies that you want data from another element on the page and the Path signifies the appropriate property.

What is the data binding concept and how binding works in WPF?

Data binding is a mechanism in WPF applications that provides a simple and easy way for Windows Runtime apps to display and interact with data. In this mechanism, the management of data is entirely separated from the way data. Data binding allows the flow of data between UI elements and data object on user interface.

What is the use of DataContext in WPF?

Every FrameworkElement can be associated with a DataContext which will be used as the default data source during binding, if no other data source is specified in the binding code. Also, the children of this FrameworkElement auotmatically inherit this setting.

What is binding path in WPF?

Binding path syntax. Use the Path property to specify the source value you want to bind to: In the simplest case, the Path property value is the name of the property of the source object to use for the binding, such as Path=PropertyName . Subproperties of a property can be specified by a similar syntax as in C#.


2 Answers

you can access an ancestors DataContext like so:

<ComboBox ItemsSource="{Binding DataContext.Departments, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}}"
                                  SelectedValue="{Binding Department}"/>
like image 190
Markus Hütter Avatar answered Oct 04 '22 17:10

Markus Hütter


In most cases I use DataContext as Path root:

{Binding Path=DataContext.MyProperty,ElementName=MyElement}
{Binding Path=DataContext.MyProperty,RelativeSource={RelativeSource AncestorType=MyAnsectorTypr}
like image 24
Marat Khasanov Avatar answered Oct 04 '22 17:10

Marat Khasanov