我正在尝试自定义 DataGridColumnHeader 以显示多个文本字段而不是
仅显示 DataGridColumn.Header 属性提供的标题文本
如果我没有错过任何东西,我只需要创建一个 DataTemplate 并绑定到属性
父对象的。这适用于 DataGridColumn.Header 属性但是
绑定到附加属性失败。
为了完整起见,附加财产的实施:
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));
}
Xaml-Markup中的用法:
<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>
我非常感谢任何澄清我在这里缺少的评论或网络链接。 提前谢谢。
答案 0 :(得分:3)
您应该使用多值转换器(msdn)。
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>
代码隐藏:
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();
}
}
我认为更好的解决方案是创建新类,例如HeaderData
,之后您可以在xaml中创建它的实例并绑定到此类。
示例:
用于保存标题数据的类:
class HeaderData
{
public string Name { get; set; }
public string Unit { get; set; }
}
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>
答案 1 :(得分:1)
乍一看,你的代码是正常的,应该可行。但是,当您的依赖项属性设置为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>
在您的情况下,该属性不起作用,因为有必要指明属性的来源,例如:ElementName
,Source
。因此,只需在参数DataGridTextColumn
中添加ElementName
的名称:
<TextBlock Text="{Binding Path=(local:CustomHeader.Unit), ElementName=SpeedColumn}" />