Привязка к значению ячейки WPF DataGrid из шаблона - PullRequest
2 голосов
/ 08 июня 2011

У меня есть коллекция пользовательских объектов данных, которые я отображаю в DataGrid.Столбцы создаются динамически во время выполнения.Некоторые из столбцов являются TemplateColumns, которые отображают значение как индикатор выполнения с соответствующим текстом в TextBlock;сама панель прогресса определяется из стиля:

private string CreateProgressBarColumnTemplate(string fieldName)
{
    StringBuilder CellTemp = new StringBuilder();
    CellTemp.Append("<DataTemplate ");
    CellTemp.Append("xmlns='http://schemas.microsoft.com/winfx/");
    CellTemp.Append("2006/xaml/presentation' ");
    CellTemp.Append("xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>");
    CellTemp.Append(String.Format("<ProgressBar Margin=\"0,1,0,0\" MinWidth=\"100\" MaxWidth=\"Infinity\" MaxHeight=\"Infinity\" Width=\"Auto\" Height=\"Auto\" HorizontalAlignment=\"Stretch\"  VerticalAlignment=\"Stretch\" Value=\"{{Binding {0}}}\" Style=\"{{StaticResource ProgressBarStyle}}\"/>", fieldName));
    CellTemp.Append("</DataTemplate>");
    return CellTemp.ToString();
}

private DataGridTemplateColumn CreateProgressBarTemplateColumn(string fieldName, string columnHeader)
{
    DataGridTemplateColumn column = new DataGridTemplateColumn();
    column.CanUserSort = true;
    column.CanUserResize = false;
    column.Header = columnHeader;
    column.CellTemplate = (DataTemplate)XamlReader.Parse(CreateProgressBarColumnTemplate(fieldName)); //display template
    return column;
}
<Style x:Key="ProgressBarStyle" TargetType="ProgressBar">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ProgressBar">
                <Border BorderBrush="#BBC6C4" BorderThickness="1" CornerRadius="5" Padding="1">
                    <Grid x:Name="PART_Track" >
                        <Rectangle x:Name="PART_Indicator" HorizontalAlignment="Left" RadiusX="5" RadiusY="5">
                            <Rectangle.Fill>
                                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                    <GradientStop Color="#FF1D5666" Offset="1"/>
                                    <GradientStop Color="#FF09B6FF"/>
                                </LinearGradientBrush>
                            </Rectangle.Fill>
                        </Rectangle>
                        <TextBlock FontFamily="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=FontFamily}" 
                                   FontSize="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=FontSize}" 
                                   FontWeight="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=FontWeight}" 
                                   TextAlignment="Center" 
                                   Background="Transparent" 
                                   DataContext="{TemplateBinding Value}" 
                                   Foreground="{Binding Converter={StaticResource ValueToColor}}" x:Name="ProgressText" 
                                   Margin="0,-3,0,0" 
                                   Text="{Binding Converter={StaticResource DoubleToPercentage}}"
                                   />
                    </Grid>              
                </Border>       
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Как видите, TextBlock DataContext имеет значение Value для свойства progressbar, а TextBlock.Text устанавливается из него.

Проблема в том, что свойство Value не может быть выше, чем MaxValue (значение, кажется, установлено в MaxValue, если я пытаюсь назначить большее значение), и мой TextBlock.Text всегда будет показывать 100%, даже если фактическое значение ячейки больше этого.

Проблема в том, как связать свойство TextBlock.Text с фактическим значением ячейки (свойство динамического) в моем пользовательском объекте данных, а не с индикатором выполнения?

1 Ответ

1 голос
/ 08 июня 2011

Вы можете использовать свойство ProgressBar.Tag для передачи значения TextBlock в ControlTemplate.Но на самом деле это должен быть пользовательский элемент управления (например, MyProgressBar), который предоставляет новое свойство зависимости (например, текст).

Чтобы использовать тег, добавьте:

CellTemp.Append(String.Format("<ProgressBar ... Tag=\"{{Binding {0}}}\" ... />", fieldName));

привязать к нему свой текстовый блок:

<TextBlock ... DataContext="{TemplateBinding Tag}" ... />
...