问题
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?
回答1:
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/
来源:https://stackoverflow.com/questions/34817417/update-wpf-from-net-4-to-4-5-2-datagridtextcolumn-visibility-datacontext-refer