问题
I have a DataGrid
which has a bound UI control in its header. The binding is to a a field in a view model. The grid is inside a TabControl
. When the grid is on the initial tab in the tab control, all works well.
However, when the grid isn't on the initial tab, no binding seems to take place. There's no console output, value converters aren't being invoked, trace level logging isn't reporting anything.
Here's a trivial, reproducible example:
View Model
public class ViewModel : INotifyPropertyChanged
{
private string _camel = "Bertie";
public string Camel
{
get => _camel;
set
{
if (value == _camel) return;
_camel = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
MainWindow.xaml
<Window x:Class="ThingsWithHumps.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:thingsWithHumps="clr-namespace:ThingsWithHumps"
mc:Ignorable="d"
Height="350" Width="350">
<Window.DataContext>
<thingsWithHumps:ViewModel/>
</Window.DataContext>
<TabControl>
<!-- This TabItem prevents the TextBlock being bound -->
<TabItem Header="Troublesome tab"/>
<TabItem Header="Humps">
<DataGrid AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>
<!-- Troublesome binding -->
<TextBlock Text="{Binding Path=DataContext.Camel,
UpdateSourceTrigger=PropertyChanged,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}}" />
</DataGridTemplateColumn.Header>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</TabItem>
</TabControl>
</Window>
MainWindow.xaml.cs
namespace ThingsWithHumps
{
public partial class MainWindow
{
public MainWindow() => InitializeComponent();
}
}
回答1:
After trying to fix your issue for a few minutes without success, i've found a solution online which seems to fix your issue.
http://www.thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/
I've tried it and it works! Good luck!
Heres the xaml code
<TabControl>
<!-- This TabItem prevents the TextBlock being bound -->
<TabItem Header="Troublesome tab"/>
<TabItem Header="Humps">
<DataGrid AutoGenerateColumns="False">
<DataGrid.Resources>
<local:BindingProxy x:Key="proxy" Data="{Binding}" />
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>
<!-- Troublesome binding -->
<TextBlock Text="{Binding Path=Data.Camel,
UpdateSourceTrigger=PropertyChanged,
Source={StaticResource proxy}}" />
</DataGridTemplateColumn.Header>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</TabItem>
</TabControl>
And the Binding Proxy class :
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));
}
来源:https://stackoverflow.com/questions/52461090/binding-not-working-in-datagrid-column-header-when-inside-non-primary-tabitem