Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding Datacontext in Resources

I have a problem with binding a value in the Resource of a DataGrid. Outside of the resources-Tag it works perfectly, but inside it doesn't work. I think maybe the Datacontext changed or is null. I don't know what to do. I read something about freezables, but I didn't get them to work too. Is that the solution or is that, what I'm doing not possible. Here my code with the non-working and the working part - just for demonstration. I need the Contextmenu in the Resources-Section to get it only, if clicked on the header-row.

<UserControl x:Class="testapp.test.testManager.Window"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:testapp.test.testManager" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="600"
         DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}">    
<Grid> 
    <DataGrid ItemsSource="{Binding Lst, UpdateSourceTrigger=PropertyChanged}" 
              AutoGeneratingColumn="dg_AutoGeneratingColumn">
        <DataGrid.Resources>
            <ContextMenu x:Key="DataGridColumnHeaderContextMenu">
                <MenuItem Header="{StaticResource General}">
                    <!-- HERE the Binding cannot find "TestCheck" -->
                    <CheckBox Content="Testentry Header" IsChecked="{Binding TestCheck, UpdateSourceTrigger=PropertyChanged,Mode=OneWay}"/>
        <!-- ... --->                    
                </MenuItem>                    
            </ContextMenu>
            <Style TargetType="{x:Type DataGridColumnHeader}">
                <Setter Property="ContextMenu" Value="{StaticResource DataGridColumnHeaderContextMenu}" />
            </Style>
        </DataGrid.Resources>           
        <DataGrid.ContextMenu>
            <ContextMenu>
                <MenuItem Header="{StaticResource General}">
                    <!-- Here the Binding can find "TestCheck" -->
                    <CheckBox Content="Testentry" IsChecked="{Binding TestCheck, UpdateSourceTrigger=PropertyChanged,Mode=OneWay}"/>
                    <!-- ... -->
                </MenuItem>
            </ContextMenu>
        </DataGrid.ContextMenu>            
    </DataGrid>
</Grid>

like image 271
Hunv Avatar asked Feb 02 '14 00:02

Hunv


People also ask

What is the DataContext?

The DataContext is the source of all entities mapped over a database connection. It tracks changes that you made to all retrieved entities and maintains an "identity cache" that guarantees that entities retrieved more than one time are represented by using the same object instance.

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.

How does binding work in C#?

C# interfaces - Blazor, API, UWP, WPF, Office Data binding allows the flow of data between UI elements and data object on user interface. When a binding is established and the data or your business model changes, then it reflects the updates automatically to the UI elements and vice versa.

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.


1 Answers

Issue is ContextMenu doesn't lie in same Visual tree as that of DataGrid and hence can't inherit DataContext of DataGrid.

You can use x:Reference to get the DataGrid instance and bind with it's DataContext. (x:Reference is available from WPF 4.0)

Give x:Name to dataGrid and bind with it:

<DataGrid ItemsSource="{Binding Lst, UpdateSourceTrigger=PropertyChanged}"
          x:Name="dataGrid">
   <DataGrid.Resources>
       <ContextMenu x:Key="DataGridColumnHeaderContextMenu">
         <MenuItem Header="{StaticResource General}">
            <CheckBox Content="Testentry Header"
                      IsChecked="{Binding DataContext.TestCheck,
                                          Source={x:Reference dataGrid}}"/>
....
</DataGrid>

Also you can achieve that using Freezable class like you mentioned in question. Refer to my answer over here for the details to achieve that via Freezable.

like image 108
Rohit Vats Avatar answered Oct 05 '22 10:10

Rohit Vats