Привязка столбца DataGrid DataTemplate к присоединенному свойству
Я пытаюсь настроить 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-разметке:
<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>
Я действительно ценю любой комментарий или веб-ссылку, которая разъясняет то, что я пропускаю здесь Заранее спасибо.
2 ответа
Вы должны использовать многозначный преобразователь ( 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>
На первый взгляд ваш код нормальный, должен работать. Но когда ваше свойство зависимости установлено 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}" />