wpf 将 DataGrid 列 DataTemplate 绑定到附加属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17898208/
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
Binding DataGrid Column DataTemplate to Attached Property
提问by LaWi
I am trying to customize a DataGridColumnHeaderto show multiple text fields instead of
showing only the header text provided by DataGridColumn.Headerproperty.
If i didn't miss something, i just have to create a DataTemplateand bind to the properties
of the parent object. This works fine for the DataGridColumn.Headerproperty but
binding to attached property fails.
我正在尝试自定义DataGridColumnHeader以显示多个文本字段,而不是
仅显示DataGridColumn.Header属性提供的标题文本。
如果我没有遗漏什么,我只需要创建一个DataTemplate并绑定到
父对象的属性。这适用于DataGridColumn.Header属性,但
绑定到附加属性失败。
For the sake of completeness, implementation of the attached property:
为了完整起见,附加属性的实现:
public static class CustomHeader
{
public static string GetUnit(DependencyObject obj) { return (string)obj.GetValue(UnitProperty); }
public static void SetUnit(DependencyObject obj, string value) { obj.SetValue(UnitProperty, value); }
public static readonly DependencyProperty UnitProperty = DependencyProperty.RegisterAttached(
"Unit", typeof(string), typeof(CustomHeader), new FrameworkPropertyMetadata(null));
}
Usage in the Xaml-Markup:
Xaml 标记中的用法:
<DataGrid x:Name="tObjectDataGrid" Margin="10,50,10,10"
AutoGenerateColumns="False" EnableRowVirtualization="True"
ItemsSource="{Binding ObjectList}"
RowDetailsVisibilityMode="VisibleWhenSelected" >
<DataGrid.Resources>
<DataTemplate x:Key="CustomHeaderTemplate">
<StackPanel>
<TextBlock Text="{Binding}" />
<TextBlock Text="{Binding Path=(cust:CustomHeader.Unit)}" /> <-- attached binding doesn't work :(
</StackPanel>
</DataTemplate>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn x:Name="SpeedColumn"
Width="1*"
Binding="{Binding Speed}"
Header="Speed"
HeaderTemplate="{StaticResource CustomHeaderTemplate}"
cust:CustomHeader.Unit="[m/s]" />
</DataGrid.Columns>
</DataGrid>
I really appreciate any comment or weblink that clarifies what i am missing here. Thanks in advance.
我非常感谢任何澄清我在这里遗漏的评论或网络链接。提前致谢。
采纳答案by kmatyaszek
You should use multi value converter (msdn).
您应该使用多值转换器 ( msdn)。
XAML:
XAML:
<DataGrid x:Name="tObjectDataGrid" Margin="10,50,10,10"
AutoGenerateColumns="False" EnableRowVirtualization="True"
ItemsSource="{Binding ObjectList}"
RowDetailsVisibilityMode="VisibleWhenSelected" >
<DataGrid.Resources>
<cust:UnitConverter x:Key="unitCon" />
<DataTemplate x:Key="CustomHeaderTemplate">
<StackPanel>
<TextBlock Text="{Binding}" />
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource unitCon}">
<Binding Path="Columns" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=DataGrid}" />
<Binding Path="." />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
</DataTemplate>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn x:Name="SpeedColumn"
Width="1*"
Binding="{Binding Speed}"
Header="Speed"
HeaderTemplate="{StaticResource CustomHeaderTemplate}"
cust:CustomHeader.Unit="[m/s]" />
<DataGridTextColumn x:Name="SpeedColumn2"
Width="1*"
Binding="{Binding Speed2}"
Header="Speed2"
HeaderTemplate="{StaticResource CustomHeaderTemplate}"
cust:CustomHeader.Unit="[km/h]" />
</DataGrid.Columns>
</DataGrid>
Code-behind:
代码隐藏:
public class UnitConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string result = null;
ObservableCollection<DataGridColumn> columns = values[0] as ObservableCollection<DataGridColumn>;
string headerName = values[1].ToString();
var coll = columns.Where(x => x.Header.ToString() == headerName).FirstOrDefault();
if (coll != null)
result = CustomHeader.GetUnit(coll);
return result;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
I think that better solution will be create new class e.g HeaderDataand after that you can create instance of it in xaml and binding to this class.
我认为更好的解决方案是创建新类,例如HeaderData,之后您可以在 xaml 中创建它的实例并绑定到这个类。
Example:
例子:
Class to hold header data:
保存标题数据的类:
class HeaderData
{
public string Name { get; set; }
public string Unit { get; set; }
}
XAML code:
XAML 代码:
<DataGrid x:Name="tObjectDataGrid" Margin="10,50,10,10"
AutoGenerateColumns="False" EnableRowVirtualization="True"
ItemsSource="{Binding ObjectList}"
RowDetailsVisibilityMode="VisibleWhenSelected" >
<DataGrid.Resources>
<DataTemplate x:Key="CustomHeaderTemplate">
<StackPanel>
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding Unit}" />
</StackPanel>
</DataTemplate>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn x:Name="SpeedColumn"
Width="1*"
Binding="{Binding Speed}"
HeaderTemplate="{StaticResource CustomHeaderTemplate}">
<DataGridTextColumn.Header>
<cust:HeaderData Name="Speed" Unit="[m/s]" />
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn x:Name="SpeedColumn2"
Width="1*"
Binding="{Binding Speed2}"
HeaderTemplate="{StaticResource CustomHeaderTemplate}">
<DataGridTextColumn.Header>
<cust:HeaderData Name="Speed2" Unit="[km/h]" />
</DataGridTextColumn.Header>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
回答by Anatoliy Nikolaev
At first glance, your code is normal, should work. But when your dependency property is set to DataGridTextColumn, SetUnitnot called and the variable Unitvalue NULL. I tried to assign a value of attached dependency property in Window(since it attached, you can set its value anywhere) in this case must work:
乍一看,你的代码是正常的,应该可以工作。但是当您的依赖属性设置为 时DataGridTextColumn,SetUnit不会调用和变量Unit值NULL。我试图分配一个附加依赖属性的值Window(因为它附加了,你可以在任何地方设置它的值)在这种情况下必须工作:
<Window x:Class="DataGridAttachedHelp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DataGridAttachedHelp"
local:CustomHeader.Unit="[m/s]"
Name="MyWindow"
Title="MainWindow" Height="350" Width="525"
WindowStartupLocation="CenterScreen">
<Grid>
<DataGrid x:Name="tObjectDataGrid" Margin="10,50,10,10"
AutoGenerateColumns="False" EnableRowVirtualization="True"
RowDetailsVisibilityMode="VisibleWhenSelected" >
<DataGrid.Resources>
<DataTemplate x:Key="CustomHeaderTemplate">
<StackPanel>
<TextBlock Text="{Binding}" />
<TextBlock Text="{Binding Path=(local:CustomHeader.Unit), ElementName=MyWindow}" />
</StackPanel>
</DataTemplate>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn x:Name="SpeedColumn" Width="1*" Binding="{Binding Speed}" Header="Speed"
HeaderTemplate="{StaticResource CustomHeaderTemplate}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
In your case the property did not work, because it is necessary to indicate the source of the properties, for example: ElementName, Source. Therefore, simply add the name of DataGridTextColumnin parameter ElementName:
在您的情况下,该属性不起作用,因为必须指明属性的来源,例如:ElementName, Source。因此,只需添加DataGridTextColumnin 参数的名称ElementName:
<TextBlock Text="{Binding Path=(local:CustomHeader.Unit), ElementName=SpeedColumn}" />

