WPF 数据网格标题文本绑定

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1658397/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 21:09:42  来源:igfitidea点击:

WPF datagrid header text binding

wpfdata-bindingdatagrid

提问by Berryl

The column header of the DataGrid is not a FrameWork element for some reason, and so you cannot use bindings to set things like the header text. Please correct me if that is wrong of if that has changed with .NET 4.0 (I am using the latest WPFToolkit from CodePlex now).

由于某种原因,DataGrid 的列标题不是 FrameWork 元素,因此您不能使用绑定来设置标题文本之类的内容。如果 .NET 4.0 发生了变化,请纠正我(我现在使用的是 CodePlex 的最新 WPFToolkit)。

I am trying to use the DataGrid for a time sheet presentation where the day's date should be part of the header text (ie, "Sun, Nov 01"), and I have the following in my XAML:

我正在尝试使用 DataGrid 进行时间表演示,其中当天的日期应该是标题文本的一部分(即“Sun, Nov 01”),并且我的 XAML 中有以下内容:

        <dg:DataGrid.Columns>
        <dg:DataGridTextColumn Header="Description" Width="Auto" Binding="{Binding Description}" IsReadOnly="True"/>
        <dg:DataGridTextColumn Header="Mon" Width="50" Binding="{Binding Allocations[0].Amount}"  />
... every other day of the week ....
        <dg:DataGridTextColumn Header="Sun" Width="50" Binding="{Binding Allocations[6].Amount}"  />
        <dg:DataGridTextColumn Header="Total" MinWidth="50" Binding="{Binding TotalAllocatedAmount}" IsReadOnly="True" />
    </dg:DataGrid.Columns>

I'd like to use the same AllocationViewModel I am using for data (ie, "{Binding Allocations[0].Amount}" and bind it's DisplayName property to the header text. Can someone show me how to do that? If I have to use a static resource, how can I get the DataContext in there?

我想使用与数据相同的 AllocationViewModel(即“{Binding Allocations[0].Amount}”并将其 DisplayName 属性绑定到标题文本。有人可以告诉我怎么做吗?如果我有要使用静态资源,如何在其中获取 DataContext?

EDIT ---------------- PREFERRED WORK-AROUND

编辑 ---------------- 首选解决方法

Josh Smith had posted about a DataContextSpyawhile back, and it is the cleanest workaround I have come across to this problem. Here is the class that makes it work:

Josh Smith不久前发布了关于DataContextSpy 的帖子,这是我遇到的最干净的解决方法。这是使其工作的类:

/// <summary>
/// Workaround to enable <see cref="DataContext"/> bindings in situations where the DataContext is not redily available. 
/// </summary>
/// <remarks>http://blogs.infragistics.com/blogs/josh_smith/archive/2008/06/26/data-binding-the-isvisible-property-of-contextualtabgroup.aspx</remarks>
public class DataContextSpy : Freezable
{
    public DataContextSpy()
    {
        // This binding allows the spy to inherit a DataContext.
        BindingOperations.SetBinding(this, DataContextProperty, new Binding());
    }

    public object DataContext
    {
        get { return GetValue(DataContextProperty); }
        set { SetValue(DataContextProperty, value); }
    }

    // Borrow the DataContext dependency property from FrameworkElement.
    public static readonly DependencyProperty DataContextProperty = FrameworkElement
        .DataContextProperty.AddOwner(typeof (DataContextSpy));

    protected override Freezable CreateInstanceCore()
    {
        // We are required to override this abstract method.
        throw new NotImplementedException();
    }
}

With this in place, I can hiHyman the DC I need in xaml:

有了这个,我可以在 xaml 中劫持我需要的 DC:

    <dg:DataGrid.Resources>
        <behavior:DataContextSpy x:Key="spy" DataContext="{Binding Allocations}" />
    </dg:DataGrid.Resources>

And then apply as needed via binding:

然后根据需要通过绑定应用:

            <dg:DataGridTextColumn Header="{Binding Source={StaticResource spy}, Path=DataContext[0].DisplayName}" 
                               Width="50" Binding="{Binding Allocations[0].Amount}"  />

Suh-weet!

嘘!

回答by mmichtch

This is the easy way to bind the DataGridTextColumn header to the data context:

这是将 DataGridTextColumn 标题绑定到数据上下文的简单方法:

<DataGrid x:Name="summaryGrid" Grid.Row="3" AutoGenerateColumns="False" IsReadOnly="True" CanUserAddRows="False">
       <DataGrid.Columns>
            <DataGridTextColumn Header="Hard Coded Title" Width="*"/>
            <DataGridTextColumn Width="100">
                <DataGridTextColumn.Header>
                    <TextBlock Text="{Binding DataContext.SecondColumnTitle, 
                                              RelativeSource={RelativeSource AncestorType={x:Type local:MainWindow}}}"/>
                </DataGridTextColumn.Header>
            </DataGridTextColumn>
            <DataGridTextColumn Width="150">
                <DataGridTextColumn.Header>
                    <TextBlock Text="{Binding DataContext.ThirdColumnTitle, 
                                              RelativeSource={RelativeSource AncestorType={x:Type local:MainWindow}}}"/>
                </DataGridTextColumn.Header>
            </DataGridTextColumn>
        </DataGrid.Columns>
    </DataGrid>

You will obviously need to have properties: SecondColumnTitleand ThirdColumnTitleimplemented on your data context class.

您显然需要拥有 properties:SecondColumnTitleThirdColumnTitle在您的数据上下文类上实现。

I have this solution working in .net 4.5 and did not have a chance nor reason to try it in earlier versions of the framework.

我有这个解决方案在 .net 4.5 中工作,并且没有机会也没有理由在框架的早期版本中尝试它。

回答by Philipp Schmid

BTW, in Silverlight(tested with SL 3.0) you can simply use the Header property as the DataContextfor the ControlTemplateset via HeaderStyle (see my related question on SO).

顺便说一句,在Silverlight(用 SL 3.0 测试)中,您可以简单地使用Header 属性作为通过 HeaderStyle 设置的ControlTemplate的 DataContext(请参阅我关于 SO 的相关问题)。

I just tried this solution in WPF 3.5 using the WPF Toolkit DataGridand it works!

我刚刚在 WPF 3.5 中使用WPF Toolkit DataGrid尝试了这个解决方案,它有效

回答by Anatoliy Nikolaev

My solution allows writing a single line in DataGridColumnwith the name of the property that need to bind. He has the following features:

我的解决方案允许在DataGridColumn需要绑定的属性名称中写入一行。他有以下特点:

  • There is support for DataGridTextColumn
  • There is support for DataGridTemplateColumn
  • Set StringFormatfor each column
  • Specify a static value for the StringFormat
  • Fully complies with MVVM pattern
  • 有支持 DataGridTextColumn
  • 有支持 DataGridTemplateColumn
  • StringFormat为每一列设置
  • 指定静态值 StringFormat
  • 完全符合MVVM模式

Example, which is below, includes StringFormat(he should stand before the PropertyPath):

下面的示例包括StringFormat(他应该站在 之前PropertyPath):

<DataGridTextColumn Behaviors:DataGridHeader.StringFormat="StringFormat: {0:C}"
                    Behaviors:DataGridHeader.PropertyPath="HeaderValueOne" ... /> 

Equivalent to a this line:

相当于一条这条线:

<DataGridTextColumn HeaderStringFormat="{0:C}"
                    Header="{Binding Path=HeaderValueOne}" ... />

Who need more examples of solutions and features, please read below.

谁需要更多解决方案和功能的示例,请阅读以下内容。

Linkfor the sample project.

Link对于示例项目。



Notes about the solution

Notes about the solution

From all the solutions that I have seen earlier, the easiest for me turned out to be this example:

从我之前看到的所有解决方案中,对我来说最简单的解决方案是这样的example

<DataGridTextColumn Binding="{Binding Name}">
    <DataGridTextColumn.HeaderTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Path=DataContext.YourPropertyName,
                                      RelativeSource={RelativeSource AncestorType={x:Type SomeControl}}" />
         </DataTemplate>
    </DataGridTextColumn.HeaderTemplate>
</DataGridTextColumn>        

Please pay attention to DataGridTextColumn.HeaderTemplate, if was used DataGridTextColumn.Header, then for .NET framework below version 4.5 and for Silverlight would produce an exception:

请注意DataGridTextColumn.HeaderTemplate,如果使用DataGridTextColumn.Header了 .NET 框架低于 4.5 和 Silverlight 会产生异常:

Header property does not support UIElements

Header 属性不支持 UIElements

It would seem that what is necessary? I wanted to find a solution that would allow to write a single line in DataGridColumnwith the name of the property that need to bind.

似乎有什么必要?我想找到一个解决方案,允许在DataGridColumn需要绑定的属性名称中写入一行。

And here's what happened:

这就是发生的事情:

<DataGridTextColumn Behaviors:DataGridHeader.PropertyPath="HeaderValueOne" // Attached dependency property 

This construction similar to this:

这种结构类似于:

<DataGridTextColumn Header="{Binding Path=HeaderValueOne}" ... />

Also is possible to use StringFormatfor each column like this:

也可以StringFormat像这样用于每一列:

<DataGridTextColumn Behaviors:DataGridHeader.StringFormat="StringFormat: {0:C}"
                    Behaviors:DataGridHeader.PropertyPath="TestStringFormatValue" ... />

And there is the ability to specify a staticvalue for the StringFormat:

并且可以为 指定静态StringFormat

<DataGridTextColumn Behaviors:DataGridHeader.StringFormat="{x:Static Member=this:TestData.TestStaticStringFormatValue}" // public static string TestStaticStringFormatValue = "Static StringFormat: {0}$";
                    Behaviors:DataGridHeader.PropertyPath="TestStringFormatValue"

Here is the original DataTemplate, which is dynamically set to the column:

这是原始的DataTemplate,它被动态设置为列:

<DataTemplate>
    <TextBlock Text="{Binding Path=DataContext.YourPropertyName,
                              StringFormat="YourStringFormat",
                              RelativeSource={RelativeSource AncestorType={x:Type DataGridCellsPanel}}}" />
</DataTemplate>

In order to RelativeSourcedid not depend on the type of DataContext, I took great solutionfrom Mr.Bruno.

为了RelativeSource不依赖的类型DataContext,我solution从先生那里得到了很大的帮助Bruno

In this case, DataGridCellsPanelcontains the correct DataContext, which is set for a parent DataGrid.

在这种情况下,DataGridCellsPanel包含为父 DataGrid 设置的正确 DataContext。

Below is the basic code that is performed all the magic:

以下是执行所有魔术的基本代码:

IsSetHeader PropertyChanged handler

IsSetHeader PropertyChanged handler

private static void IsSetHeader(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
    var textColumn = sender as DataGridTextColumn;
    var templateColumn = sender as DataGridTemplateColumn;
    string path = e.NewValue as string;

    if ((textColumn == null) & (templateColumn == null)) 
    {
        return;
    }

    if (String.IsNullOrEmpty(path) == false)
    {
        currentStringFormat = ReturnStringFormat(textColumn, templateColumn);
        dataTemplate = CreateDynamicDataTemplate(path, currentStringFormat);

        if (dataTemplate != null)
        {
            if (textColumn != null)
                textColumn.HeaderTemplate = dataTemplate;

            if (templateColumn != null)
                templateColumn.HeaderTemplate = dataTemplate;
        }
    }
}

CreateDynamicDataTemplate

CreateDynamicDataTemplate

private static DataTemplate CreateDynamicDataTemplate(string propertyPath, string stringFormat)
{
    var pc = new ParserContext();
    MemoryStream sr = null;

    string xaml = GetXamlString(propertyPath, stringFormat);            
    sr = new MemoryStream(Encoding.ASCII.GetBytes(xaml));

    pc.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
    pc.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");

    return XamlReader.Load(sr, pc) as DataTemplate;
}

GetXamlString

GetXamlString

private static string GetXamlString(string propertyPath, string stringFormat)
{
    #region Original PropertyPath for TextBlock

    // {Binding Path=DataContext.YourProperty, RelativeSource={RelativeSource AncestorType={x:Type DataGridCellsPanel}}}"
    // Thanks to Bruno (https://stackoverflow.com/users/248118/bruno) for this trick

    #endregion

    var sb = new StringBuilder();

    sb.Append("<DataTemplate><TextBlock Text=\"{Binding Path=DataContext.");
    sb.Append(propertyPath);
    sb.Append(", StringFormat=");
    sb.Append(stringFormat);
    sb.Append(", RelativeSource={RelativeSource AncestorType={x:Type DataGridCellsPanel}}}\" /></DataTemplate>");

    return sb.ToString();
}

StringFormatmust appear before the PropertyPath, because it is optional. In order to for columns, who did not have it is not an exception occurs, I registered try-catch in GetStringFormat:

StringFormat必须出现在 PropertyPath 之前,因为它是可选的。为了对于列,没有它的人不会发生异常,我注册了 try-catch GetStringFormat

 public static string GetStringFormat(DependencyObject DepObject)
 {
    try
    {
        return (string)DepObject.GetValue(StringFormatProperty);
    }

    catch 
    {
        return String.Empty;
    }
 }

Plus:do not write in methods try-catch block, that are trying to get the value.

另外:不要在尝试获取值的方法 try-catch 块中写入。

Minus:The minus for every missed StringFormatexception will be generated once when the program starts. If it is critical for you, you can always specify the StringFormat="null"for the column.

减号:StringFormat程序启动时,将为每个错过的异常生成一次减号。如果它对您很重要,您始终可以StringFormat="null"为列指定。

Just in case, show the full code of project:

以防万一,显示项目的完整代码:

public static class DataGridHeader
{
    #region Private Section

    private static string textColumnStringFormat = null;
    private static string templateColumnStringFormat = null;
    private static string currentStringFormat = null;
    private static DataTemplate dataTemplate = null;

    #endregion

    #region PropertyPath DependencyProperty

    public static readonly DependencyProperty PropertyPathProperty;

    public static void SetPropertyPath(DependencyObject DepObject, string value)
    {
        DepObject.SetValue(PropertyPathProperty, value);
    }

    public static string GetPropertyPath(DependencyObject DepObject)
    {
        return (string)DepObject.GetValue(PropertyPathProperty);
    }

    #endregion

    #region StringFormat DependencyProperty

    public static readonly DependencyProperty StringFormatProperty;

    public static void SetStringFormat(DependencyObject DepObject, string value)
    {
        DepObject.SetValue(StringFormatProperty, value);
    }

    public static string GetStringFormat(DependencyObject DepObject)
    {
        try
        {
            return (string)DepObject.GetValue(StringFormatProperty);
        }

        catch 
        {
            return String.Empty;
        }
    }

    #endregion

    #region Constructor

    static DataGridHeader()
    {
        PropertyPathProperty = DependencyProperty.RegisterAttached("PropertyPath",
                                                                   typeof(string),
                                                                   typeof(DataGridHeader),
                                                                   new UIPropertyMetadata(String.Empty, IsSetHeader));

        StringFormatProperty = DependencyProperty.RegisterAttached("StringFormat",
                                                                   typeof(string),
                                                                   typeof(DataGridHeader),
                                                                   new UIPropertyMetadata(String.Empty));  
    }

    #endregion

    #region IsSetHeader PropertyChanged Handler

    private static void IsSetHeader(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        var textColumn = sender as DataGridTextColumn;
        var templateColumn = sender as DataGridTemplateColumn;
        string path = e.NewValue as string;

        if ((textColumn == null) & (templateColumn == null)) 
        {
            return;
        }

        if (String.IsNullOrEmpty(path) == false)
        {
            currentStringFormat = ReturnStringFormat(textColumn, templateColumn);
            dataTemplate = CreateDynamicDataTemplate(path, currentStringFormat);

            if (dataTemplate != null)
            {
                if (textColumn != null)
                    textColumn.HeaderTemplate = dataTemplate;

                if (templateColumn != null)
                    templateColumn.HeaderTemplate = dataTemplate;
            }
        }
    }

    #endregion

    #region ReturnStringFormat Helper

    private static string ReturnStringFormat(DependencyObject depObject1, DependencyObject depObject2) 
    {
        textColumnStringFormat = GetStringFormat(depObject1) as string;
        templateColumnStringFormat = GetStringFormat(depObject2) as string;

        if (String.IsNullOrEmpty(textColumnStringFormat) == false)
        {
            return textColumnStringFormat;
        }

        if (String.IsNullOrEmpty(templateColumnStringFormat) == false)
        {
            return templateColumnStringFormat;
        }

        return "null";
    }

    #endregion

    #region CreateDynamicDataTemplate Helper

    private static DataTemplate CreateDynamicDataTemplate(string propertyPath, string stringFormat)
    {
        var pc = new ParserContext();
        MemoryStream sr = null;

        string xaml = GetXamlString(propertyPath, stringFormat);            
        sr = new MemoryStream(Encoding.ASCII.GetBytes(xaml));

        pc.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
        pc.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");

        return XamlReader.Load(sr, pc) as DataTemplate;
    }

    #endregion

    #region GetXamlString Helper

    private static string GetXamlString(string propertyPath, string stringFormat)
    {
        #region Original PropertyPath for TextBlock

        // {Binding Path=DataContext.YourProperty, RelativeSource={RelativeSource AncestorType={x:Type DataGridCellsPanel}}}"
        // Thanks to Bruno (https://stackoverflow.com/users/248118/bruno) for this trick

        #endregion

        var sb = new StringBuilder();

        sb.Append("<DataTemplate><TextBlock Text=\"{Binding Path=DataContext.");
        sb.Append(propertyPath);
        sb.Append(", StringFormat=");
        sb.Append(stringFormat);
        sb.Append(", RelativeSource={RelativeSource AncestorType={x:Type DataGridCellsPanel}}}\" /></DataTemplate>");

        return sb.ToString();
    }

    #endregion
}

XAML

XAML

<Window x:Class="BindingHeaderInDataGrid.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:this="clr-namespace:BindingHeaderInDataGrid"
        xmlns:Behaviors="clr-namespace:BindingHeaderInDataGrid.AttachedBehaviors"
        WindowStartupLocation="CenterScreen"
        Title="MainWindow" Height="220" Width="600">

    <Window.DataContext>
        <this:TestData />
    </Window.DataContext>

    <Grid Name="TestGrid">
        <DataGrid Name="TestDataGrid" 
                  Width="550"
                  Height="100"
                  Margin="10"
                  VerticalAlignment="Top"
                  Background="AliceBlue">

            <DataGrid.Columns>
                <DataGridTextColumn Behaviors:DataGridHeader.StringFormat="StringFormat: {0:C}"
                                    Behaviors:DataGridHeader.PropertyPath="TestStringFormatValue"
                                    Width="100"
                                    IsReadOnly="False">

                    <DataGridTextColumn.HeaderStyle>
                        <Style TargetType="{x:Type DataGridColumnHeader}">
                            <Setter Property="Height" Value="20" />
                            <Setter Property="Background" Value="Pink" />
                            <Setter Property="Margin" Value="2,0,0,0" />
                        </Style>
                    </DataGridTextColumn.HeaderStyle>
                </DataGridTextColumn>

                <DataGridTextColumn Behaviors:DataGridHeader.StringFormat="{x:Static Member=this:TestData.TestStaticStringFormatValue}"
                                    Behaviors:DataGridHeader.PropertyPath="TestStringFormatValue"
                                    Width="2*"
                                    IsReadOnly="False">

                    <DataGridTextColumn.HeaderStyle>
                        <Style TargetType="{x:Type DataGridColumnHeader}">
                            <Setter Property="Height" Value="20" />
                            <Setter Property="Background" Value="CadetBlue" />
                            <Setter Property="Margin" Value="2,0,0,0" />
                        </Style>
                    </DataGridTextColumn.HeaderStyle>
                </DataGridTextColumn>

                <DataGridTextColumn Behaviors:DataGridHeader.PropertyPath="TestUsualHeaderValue"
                                    Width="1.5*" 
                                    IsReadOnly="False">

                    <DataGridTextColumn.HeaderStyle>
                        <Style TargetType="{x:Type DataGridColumnHeader}">
                            <Setter Property="Height" Value="20" />
                            <Setter Property="Background" Value="Gainsboro" />
                            <Setter Property="Margin" Value="2,0,0,0" />
                        </Style>
                    </DataGridTextColumn.HeaderStyle>
                </DataGridTextColumn>

                <DataGridTemplateColumn Behaviors:DataGridHeader.PropertyPath="TestTemplateColumnValue"
                                        Width="150"
                                        IsReadOnly="False">

                    <DataGridTemplateColumn.HeaderStyle>
                        <Style TargetType="{x:Type DataGridColumnHeader}">
                            <Setter Property="Height" Value="20" />
                            <Setter Property="Background" Value="Beige" />
                            <Setter Property="Margin" Value="2,0,0,0" />
                        </Style>
                    </DataGridTemplateColumn.HeaderStyle>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>

        <Button Name="ChangeHeader" 
                Width="100" 
                Height="30"
                VerticalAlignment="Bottom"
                Content="ChangeHeader" 
                Click="ChangeHeader_Click" />
    </Grid>
</Window>

Code-behind

Code-behind

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }        

    private void ChangeHeader_Click(object sender, RoutedEventArgs e)
    {
        TestData data = this.DataContext as TestData;

        data.TestStringFormatValue = "777";
        data.TestUsualHeaderValue = "DynamicUsualHeader";
        data.TestTemplateColumnValue = "DynamicTemplateColumn";
    }
}

public class TestData : NotificationObject
{
    #region TestStringFormatValue

    private string _testStringFormatValue = "1";

    public string TestStringFormatValue
    {
        get
        {
            return _testStringFormatValue;
        }

        set
        {
            _testStringFormatValue = value;
            NotifyPropertyChanged("TestStringFormatValue");
        }
    }

    #endregion

    #region TestStaticStringFormatValue

    public static string TestStaticStringFormatValue = "Static StringFormat: {0}$";

    #endregion

    #region TestUsualHeaderValue

    private string _testUsualHeaderValue = "UsualHeader";

    public string TestUsualHeaderValue
    {
        get
        {
            return _testUsualHeaderValue;
        }

        set
        {
            _testUsualHeaderValue = value;
            NotifyPropertyChanged("TestUsualHeaderValue");
        }
    }

    #endregion

    #region TestTemplateColumnValue

    private string _testTemplateColumnValue = "TemplateColumn";

    public string TestTemplateColumnValue
    {
        get
        {
            return _testTemplateColumnValue;
        }

        set
        {
            _testTemplateColumnValue = value;
            NotifyPropertyChanged("TestTemplateColumnValue");
        }
    }

    #endregion
}

回答by Mike Collins

I know this post is old, but when I looked up how to do this, this is the first entry that came up. I did not like this answer because it seemed like overkill. After more searching, I ran across this linkthe showed how to do this in the markup, using a template column.

我知道这篇文章很旧,但是当我查找如何执行此操作时,这是第一个出现的条目。我不喜欢这个答案,因为它看起来有点矫枉过正。经过更多搜索,我找到了这个链接,该链接展示了如何使用模板列在标记中执行此操作。

<DataGridTemplateColumn>
    <DataGridTemplateColumn.HeaderTemplate>
        <DataTemplate>
            **<TextBlock Text="{Binding DataContext.HeaderTitle, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />**
        </DataTemplate>
    </DataGridTemplateColumn.HeaderTemplate>
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding}" Width="200" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

回答by Aran Mulholland

**EDIT :-

**编辑 :-

You can style the DataGridColumnHeader and do some funky bindings. try hereand download the ColumnHeaderBindings.zip, it has a little test project, that is a bit of a hack, but it works

您可以设置 DataGridColumnHeader 的样式并进行一些时髦的绑定。尝试在这里下载 ColumnHeaderBindings.zip,它有一个小测试项目,有点小技巧,但它可以工作

**End Edit

**结束编辑

The Bindingon the column happens on a per rowbasis, the column is not part of the visual tree, the binding gets applied to each item in the grid, from the grids source code you can see that the property Binding has these comments

列上的绑定发生在每行的基础上,列不是可视化树的一部分,绑定被应用于网格中的每个项目,从网格源代码中可以看到属性 Binding 有这些注释

    /// <summary>
    ///     The binding that will be applied to the generated element.
    /// </summary>
    /// <remarks>
    ///     This isn't a DP because if it were getting the value would evaluate the binding.
    /// </remarks>

So binding to the columns does not make much sense, because as you have found out, when you are not part of the visual tree you have no data context.

因此绑定到列没有多大意义,因为正如您所发现的,当您不是可视化树的一部分时,您就没有数据上下文。

The same problem exists with the ComboBoxColumn when you want to bind to the items source. You can bind to a StaticResource, but StaticResources dont have a data context either. You could use an object data provider or just instantiate directly in xaml.

当您想要绑定到项目源时, ComboBoxColumn 存在同样的问题。您可以绑定到静态资源,但静态资源也没有数据上下文。您可以使用对象数据提供程序或直接在 xaml 中实例化。

but i would just create the columns in code, and set the header. this problem would just go away then.

但我只会在代码中创建列,并设置标题。这个问题就会消失。

there is a good article hereon the visual layout.

有一个很好的文章在这里的可视化布局。

回答by David

an even better solution would be to set the binding in the header's style and pass the column as the header's dataContext... (or even better: to set up an object representing the header's dataContext and pass it)

更好的解决方案是在标题的样式中设置绑定并将列作为标题的 dataContext 传递......(或者更好:设置一个表示标题的 dataContext 的对象并传递它)

see there for a way to do this :

请参阅那里的方法来做到这一点:

How to set the DataContext on a DataGrid Column Header

如何在 DataGrid 列标题上设置 DataContext

回答by Sabeen

@mmichtch's answer works well for me, you just have to create a local namespace(xmlns), which contains reference to your project as follows:

@mmichtch 的回答对我很有效,您只需要创建一个本地命名空间(xmlns),其中包含对您的项目的引用,如下所示:

xmlns:local="clr-namespace:your_project_name"

and along with it don't forget to mention the property you want to bind:

并且不要忘记提及您要绑定的属性:

                <DataGridTextColumn Width="Auto">
                <DataGridTextColumn.Header>
                    <TextBlock Text="{Binding DataContext.PropertyNameYouWantToBind, 
                                          RelativeSource={RelativeSource AncestorType={x:Type local:MainWindow}}}"/>
                </DataGridTextColumn.Header>
            </DataGridTextColumn>

it works well with VS 2010 and .net version 4.

它适用于 VS 2010 和 .net 版本 4。

回答by Heiner

I solved this by using the HeaderTemplateand binding to the DataContextof the DataGrid, using RelativeSource.

我通过使用HeaderTemplate和 绑定到DataContextDataGrid,使用解决了这个问题RelativeSource

<DataGrid ItemsSource="{Binding Items}">
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding Value1}">
            <DataGridTextColumn.HeaderTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding DataContext.ColumnTitel1, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
                </DataTemplate>
            </DataGridTextColumn.HeaderTemplate>
        </DataGridTextColumn>
    </DataGrid.Columns>
</DataGrid>

The same binding within the Headerproperty did not work out.

Header属性内的相同绑定不起作用。

回答by taysoren

I used it to populate the DataGrid Column Header.

我用它来填充 DataGrid 列标题。

技巧是在绑定模式。它的“模式”需要设置为“单向”。否则没有好处。

例子:

<DataGridTextColumn Binding="{Binding RowData}" Header="{Binding Mode=OneWay, Source={StaticResource spy},Path=DataContext.HeaderText,  FallbackValue= header text}"/>

I used a lowercase fallback value, and the value from DataContext was capitalized to assure me that the resource was not null. Also, the value from DataContext was only showing up for me at run time, during design time it displayed the fallback value. Hope this helps.

我使用了小写的回退值,并将 DataContext 中的值大写以确保资源不为空。此外,来自 DataContext 的值仅在运行时显示给我,在设计时它显示回退值。希望这可以帮助。