Update WPF from .NET 4 to 4.5.2, DataGridTextColumn Visibility DataContext reference broken
Asked Answered
E

1

0

I've upgraded a WPF project to .NET 4.5.2. In a xaml file, I have the following line.

<UserControl
        x:Class="Casa.Project.Client.Views.Projects.ProjectSearch"
        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:controls="clr-namespace:Casa.Project.Core.Wpf.Controls;assembly=Casa.Project.Core.Wpf"
        mc:Ignorable="d"
        d:DesignWidth="700"
        x:Name="ProjectSearchWindow"
    >
<UserControl.Resources>
<DataGridTextColumn x:Key="PlanNumberColumn" Header="Project #" Visibility="{Binding DataContext.ShowPlanNumber, Source={x:Reference ProjectSearchWindow}}" Binding="{Binding ProjectNumber}" />

...

ReSharper underlines the entire Visibility tag, saying "Object reference not set to an instance of an object", which produces an error. When I load up the old project that targets .NET 4, that error doesn't exist.

When I actually run the project the entire table that uses DataGridTextColumn doesn't show any of the values (which are getting loaded properly).

Is there some change that occurred from .NET 4 to .NET 4.5.2 that results in this behavior? How do I fix it?

Electrostriction answered 15/1, 2016 at 18:25 Comment(0)
E
0

So I didn't figure out why the upgrade broke it, but I did figure out a way to make it work.

The Freezable class has the ability to get DataContext passed to it even though it's not part of the visual/logical tree. We take advantage of that for this fix.

Steps

First, Create a class that 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));
}

Second, drop <helpers:BindingProxy x:Key="proxy" Data="{Binding}" /> right around your DataGridTextColumn's. Change local to the namespace of your BindingProxy class. Change DataGrid to match you're root xaml's tag. Import the namespace for your BindingProxy into your xaml file if necessary (like xmlns:helpers="clr-namespace:Casa.Project.Client.Helpers")

<DataGrid.Resources>
    <helpers:BindingProxy x:Key="proxy" Data="{Binding}" />
    <DataGridTextColumn x:Key="PlanNumberColumn" Header="Project #" Visibility="{Binding Data.ShowPlanNumber, Source={StaticResource proxy}}" Binding="{Binding ProjectNumber}" />
</DataGrid.Resources>

Final code state roughly

<UserControl
        x:Class="Casa.Project.Client.Views.Projects.ProjectSearch"
        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:helpers="clr-namespace:Casa.Project.Client.Helpers"
        xmlns:controls="clr-namespace:Casa.Project.Core.Wpf.Controls;assembly=Casa.Project.Core.Wpf"
        mc:Ignorable="d"
        d:DesignWidth="700"
        x:Name="ProjectSearchWindow"
    >
<UserControl.Resources>
    <helpers:BindingProxy x:Key="proxy" Data="{Binding}" />
    <DataGridTextColumn x:Key="PlanNumberColumn" Header="Project #" Visibility="{Binding DataContext.ShowPlanNumber, Source={x:Reference ProjectSearchWindow}}" Binding="{Binding ProjectNumber}" />

Source: http://www.thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/

Electrostriction answered 15/1, 2016 at 22:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.