2017-04-10 65 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