绑定在 DataGrid 的 ColumnHeaderStyle 中不起作用
Binding not working in DataGrid's ColumnHeaderStyle
我只是想将带有 Binding
的 DataGridTemplateColumn.Header
的 Background
设置为自定义 DependencyProperty
。我可以将它明确设置为样式中的颜色,但我需要根据某些用户偏好更改它。我不想编写代码来深入挖掘并在每个视图的每个网格中找到 headers 中的每一个。
我确定我遗漏了一些非常简单的东西,比如我没有正确设置 DataContext
,但我已经尝试了我想到的所有方法,但没有任何效果。我以前从未使用过 DataGrid
,所以我仍在尝试找出很多东西。有人请告诉我我错过了什么。
XAML:
<Window x:Class="DataGridTest.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:local="clr-namespace:DataGridTest"
mc:Ignorable="d"
Title="Data Grid Test" Height="300" Width="525"
WindowStartupLocation="CenterScreen">
<DataGrid Name="DataGrid1"
AutoGenerateColumns="False"
MaxWidth="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=Width}"
ScrollViewer.CanContentScroll="False">
<DataGrid.ColumnHeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="Background" Value="{Binding HeaderBackground}" />
</Style>
</DataGrid.ColumnHeaderStyle>
<DataGrid.Columns>
<DataGridTemplateColumn IsReadOnly="True" Width="*">
<DataGridTemplateColumn.Header>
<ComboBox Name="CB1">
<ComboBoxItem Name="CBI11" Content="Choose..." IsSelected="True" />
<ComboBoxItem Name="CBI12" Content="First Choice" />
<ComboBoxItem Name="CBI13" Content="Second Choice" />
</ComboBox>
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding Text1}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn IsReadOnly="True" Width="Auto">
<DataGridTemplateColumn.Header>
<ComboBox Name="CB2">
<ComboBoxItem Name="CBI21" Content="Choose..." IsSelected="True" />
<ComboBoxItem Name="CBI22" Content="First Choice" />
<ComboBoxItem Name="CBI23" Content="Second Choice" />
</ComboBox>
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding Text2}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Window>
C#:
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;
namespace DataGridTest
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
DataGrid1.ItemsSource = TestClass.GetTestText();
HeaderBackground = (Brush)new BrushConverter().ConvertFromString("#FF0000FF");
}
public Brush HeaderBackground
{
get { return (Brush)GetValue(HeaderBackgroundProperty); }
set
{
SetValue(HeaderBackgroundProperty, value);
RaisePropertyChanged("HeaderBackgroundProperty");
}
}
private static readonly DependencyProperty HeaderBackgroundProperty =
DependencyProperty.Register("HeaderBackground", typeof(Brush), typeof(MainWindow), new PropertyMetadata((Brush)new BrushConverter().ConvertFromString("#FFFF0000")));
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string caller = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(caller));
}
}
}
internal class TestClass : INotifyPropertyChanged
{
private Span text1;
public Span Text1
{
get { return text1; }
set
{
text1 = value;
RaisePropertyChanged();
}
}
private Span text2;
public Span Text2
{
get { return text2; }
set
{
text2 = value;
RaisePropertyChanged();
}
}
public static ObservableCollection<TestClass> GetTestText()
{
ObservableCollection<TestClass> TestList = new ObservableCollection<TestClass>();
for (int i = 0; i < 10; i++)
{
Run run1 = new Run("This is a test. ");
Hyperlink link1 = new Hyperlink(new Run("This is only a test."));
Span span1 = new Span();
span1.Inlines.AddRange(new Inline[] { run1, link1 });
Run run2 = new Run("If this was not a test, ");
Hyperlink link2 = new Hyperlink(new Run("something would be happening."));
Span span2 = new Span();
span2.Inlines.AddRange(new Inline[] { run2, link2 });
TestList.Add(new TestClass() { Text1 = span1, Text2 = span2 });
}
return TestList;
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string caller = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(caller));
}
}
}
}
为您的主要 window 命名。例如x:Name="MyWindow"
您已经为主要 window 创建了依赖项 属性 "HeaderBackground"。所以为了访问它,你需要使用 ElementName
绑定。
<DataGrid.ColumnHeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="Background" Value="{Binding ElementName=MyWindow, Path=HeaderBackground}" />
</Style>
</DataGrid.ColumnHeaderStyle>
希望对您有所帮助。
您可以只指定绑定的 RelativeSource
:
<DataGrid.ColumnHeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="Background" Value="{Binding HeaderBackground, RelativeSource={RelativeSource AncestorType=Window}}" />
</Style>
</DataGrid.ColumnHeaderStyle>
DataGridColumnHeader
的 DataContext
不是 window,这就是为什么您的原始绑定不起作用。
您可以使用 RelativeSource
绑定到可视化树中父元素的 属性,例如父元素 window.
我将我的配色方案映射到视图模型中的 MasterConfiguration class。这样我就可以即时更改它们。这对我有用。
我只是想将带有 Binding
的 DataGridTemplateColumn.Header
的 Background
设置为自定义 DependencyProperty
。我可以将它明确设置为样式中的颜色,但我需要根据某些用户偏好更改它。我不想编写代码来深入挖掘并在每个视图的每个网格中找到 headers 中的每一个。
我确定我遗漏了一些非常简单的东西,比如我没有正确设置 DataContext
,但我已经尝试了我想到的所有方法,但没有任何效果。我以前从未使用过 DataGrid
,所以我仍在尝试找出很多东西。有人请告诉我我错过了什么。
XAML:
<Window x:Class="DataGridTest.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:local="clr-namespace:DataGridTest"
mc:Ignorable="d"
Title="Data Grid Test" Height="300" Width="525"
WindowStartupLocation="CenterScreen">
<DataGrid Name="DataGrid1"
AutoGenerateColumns="False"
MaxWidth="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=Width}"
ScrollViewer.CanContentScroll="False">
<DataGrid.ColumnHeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="Background" Value="{Binding HeaderBackground}" />
</Style>
</DataGrid.ColumnHeaderStyle>
<DataGrid.Columns>
<DataGridTemplateColumn IsReadOnly="True" Width="*">
<DataGridTemplateColumn.Header>
<ComboBox Name="CB1">
<ComboBoxItem Name="CBI11" Content="Choose..." IsSelected="True" />
<ComboBoxItem Name="CBI12" Content="First Choice" />
<ComboBoxItem Name="CBI13" Content="Second Choice" />
</ComboBox>
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding Text1}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn IsReadOnly="True" Width="Auto">
<DataGridTemplateColumn.Header>
<ComboBox Name="CB2">
<ComboBoxItem Name="CBI21" Content="Choose..." IsSelected="True" />
<ComboBoxItem Name="CBI22" Content="First Choice" />
<ComboBoxItem Name="CBI23" Content="Second Choice" />
</ComboBox>
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding Text2}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Window>
C#:
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;
namespace DataGridTest
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
DataGrid1.ItemsSource = TestClass.GetTestText();
HeaderBackground = (Brush)new BrushConverter().ConvertFromString("#FF0000FF");
}
public Brush HeaderBackground
{
get { return (Brush)GetValue(HeaderBackgroundProperty); }
set
{
SetValue(HeaderBackgroundProperty, value);
RaisePropertyChanged("HeaderBackgroundProperty");
}
}
private static readonly DependencyProperty HeaderBackgroundProperty =
DependencyProperty.Register("HeaderBackground", typeof(Brush), typeof(MainWindow), new PropertyMetadata((Brush)new BrushConverter().ConvertFromString("#FFFF0000")));
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string caller = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(caller));
}
}
}
internal class TestClass : INotifyPropertyChanged
{
private Span text1;
public Span Text1
{
get { return text1; }
set
{
text1 = value;
RaisePropertyChanged();
}
}
private Span text2;
public Span Text2
{
get { return text2; }
set
{
text2 = value;
RaisePropertyChanged();
}
}
public static ObservableCollection<TestClass> GetTestText()
{
ObservableCollection<TestClass> TestList = new ObservableCollection<TestClass>();
for (int i = 0; i < 10; i++)
{
Run run1 = new Run("This is a test. ");
Hyperlink link1 = new Hyperlink(new Run("This is only a test."));
Span span1 = new Span();
span1.Inlines.AddRange(new Inline[] { run1, link1 });
Run run2 = new Run("If this was not a test, ");
Hyperlink link2 = new Hyperlink(new Run("something would be happening."));
Span span2 = new Span();
span2.Inlines.AddRange(new Inline[] { run2, link2 });
TestList.Add(new TestClass() { Text1 = span1, Text2 = span2 });
}
return TestList;
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string caller = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(caller));
}
}
}
}
为您的主要 window 命名。例如x:Name="MyWindow"
您已经为主要 window 创建了依赖项 属性 "HeaderBackground"。所以为了访问它,你需要使用 ElementName
绑定。
<DataGrid.ColumnHeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="Background" Value="{Binding ElementName=MyWindow, Path=HeaderBackground}" />
</Style>
</DataGrid.ColumnHeaderStyle>
希望对您有所帮助。
您可以只指定绑定的 RelativeSource
:
<DataGrid.ColumnHeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="Background" Value="{Binding HeaderBackground, RelativeSource={RelativeSource AncestorType=Window}}" />
</Style>
</DataGrid.ColumnHeaderStyle>
DataGridColumnHeader
的 DataContext
不是 window,这就是为什么您的原始绑定不起作用。
您可以使用 RelativeSource
绑定到可视化树中父元素的 属性,例如父元素 window.
我将我的配色方案映射到视图模型中的 MasterConfiguration class。这样我就可以即时更改它们。这对我有用。