2017-04-10 136 views
0

我只是试图将我的DataGridTemplateColumn.HeaderBackgroundBinding设置为自定义DependencyProperty。我可以明确地将其设置为样式中的颜色,但我需要根据某些用户偏好进行更改。我不想编写代码来挖掘并在每个视图中的每个网格中查找每个标题。绑定在DataGrid的ColumnHeaderStyle中不起作用

我确定我错过了一些超级简单的东西,比如我没有正确设置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)); 
      } 
     } 
    } 
} 

回答

1

你可以只指定绑定的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> 

DataGridColumnHeaderDataContext没有窗户,这就是为什么你原来的绑定不起作用。

您可以使用RelativeSource绑定到可视化树中父元素的属性,例如父窗口。

+0

看,我知道它会超级简单。谢谢!有趣的是,我还设法通过明确设置BorderBrush来获得所需的结果。我不明白为什么,但由于某种原因,当我这样做时,原始绑定(没有相关源码)起作用。 – Meloviz

1

提供一个名称的主窗口。例如x:Name="MyWindow"

您已经为主窗口创建了依赖属性“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> 

enter image description here

希望这有助于。

+0

谢谢,@Parag。你的答案给出了期望的结果,但我选择不让你的答案接受,因为我不喜欢x:如果我不需要,就命名这些东西。这是另一种有效的方式,但我很欣赏它。 +1 – Meloviz