Meloviz
Meloviz

Reputation: 581

Binding not working in DataGrid's ColumnHeaderStyle

I am just trying to set the Background of my DataGridTemplateColumn.Header with a Binding to a custom DependencyProperty. I can set it explicitly to a color in the style, but I need it to change depending on some user preferences. I don't want to have to write code to dig down and find each one of headers in each of the grids in each of my views.

I'm sure I am missing something super simple, like I'm not setting the DataContext correctly, but I've tried everything that's come to my mind, and nothing has worked. I've never used a DataGrid before, so I'm still trying to figure out a lot of stuff. Someone please tell me what I'm missing.

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));
            }
        }
    }
}

Upvotes: 0

Views: 1051

Answers (3)

Bobabooie
Bobabooie

Reputation: 21

I have my color schemes mapped to a MasterConfiguration class within my view model. That way I can change them on the fly. This worked for me.

enter image description here

Upvotes: 0

mm8
mm8

Reputation: 169350

You could just specify a RelativeSource of the binding:

<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>

The DataContext of the DataGridColumnHeader isn't the window and that's why your original binding doesn't work.

You could use a RelativeSource to bind to a property of a parent element in the visual tree, like for example the parent window.

Upvotes: 1

Parag
Parag

Reputation: 543

Give a name to your main window. e.g. x:Name="MyWindow"

You have created dependancy property "HeaderBackground" for main window. So in order to access it, you need to use ElementName binding.

<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

Hope this helps.

Upvotes: 1

Related Questions