0

For the last two days I've been trying create a data template for the header of the column based on the ACTUAL( not visible ) index of the column. Can anyone please enlighten me how to do that correctly?

<!--http://stackoverflow.com/questions/13693619/change-the-color-of-a-grid-header-using-xceed-datagrid-in-wpf-->
<ControlTemplate x:Key="HeaderTemplate" TargetType="{x:Type xcdg:ColumnManagerCell}">
    <DockPanel>
        <TextBlock DockPanel.Dock="Top" Text="{TemplateBinding Content}" x:Name="TextContainer"/>
        <TextBlock Visibility="{Binding Step, Converter={StaticResource Mapping}}" x:Name="WorkElement" DockPanel.Dock="Top" Foreground="Red" Width="100">
            <TextBlock.Text>
                <MultiBinding Converter="{StaticResource Conv}">
                    <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="ParentColumn.VisiblePosition"></Binding>
                    <Binding Path= "FileModel.Columns"></Binding>
                    <Binding ElementName="TextContainer" Path="Text"></Binding>
                    <Binding ElementName="WorkElement" Path="Text"></Binding>
                </MultiBinding>
            </TextBlock.Text>
        </TextBlock>
    </DockPanel>
</ControlTemplate>
<Style TargetType="{x:Type xcdg:ColumnManagerRow}">
    <Setter Property="Background" Value="AliceBlue"/>
    <Setter Property="BorderBrush" Value="Black"/>
    <Setter Property="AllowColumnReorder" Value="False"/>
</Style>

<Style TargetType="{x:Type xcdg:ColumnManagerCell}">
    <Setter Property="Template" Value="{StaticResource HeaderTemplate}"/>
</Style>

Converter:

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
    var context = values[1] as IEnumerable<MatrixImportColumn>;
    if ( values[1] != null && values[0] != null 
        && values[0] != DependencyProperty.UnsetValue
        && values[1] != DependencyProperty.UnsetValue )
    {
        var itemContext = (int)values[0];
        var original = values[2] as string;
        if (context != null)
        {
            var dp = context.FirstOrDefault(x => x.ColumnIndex == itemContext);
            return string.Format("{0} -> {1}", original, dp.MappedInto);
        }

    return string.Format("{0} -> [Unmapped]", original);
    }

    var val = values[3] as string;
    if (val != string.Empty)
        return val;
    else return "";
}

My model is :

public DataTable Model
{
    get { return _model; }
    set
    {
        _model = value;
        OnPropertyChanged();
    }
}
Christo S. Christov
  • 2,268
  • 3
  • 32
  • 57

2 Answers2

2

The ColumnManagerCell derives from Cell which has a ParentColumn property and the parent column has a VisiblePosition property. Bind to this for the visible column index (will change when moving columns around).

Generally:

<TextBlock Text="{Binding Path=ParentColumn.VisiblePosition,RelativeSource={RelativeSource AncestorType={x:Type xd:Cell}}}"/>

For your ControlTemplate:

<TextBlock Text="{Binding Path=ParentColumn.VisiblePosition,RelativeSource={RelativeSource TemplatedParent}}"/>

I use xd as xmlns:xd="http://schemas.xceed.com/wpf/xaml/datagrid"

In order to have a consistent visible position, you can disable column reordering in the ColumnManagerRow style.

<Style TargetType="xd:ColumnManagerRow">
    <Setter Property="AllowColumnReorder" Value="False"/>
</Style>

Edit

Here is a working example, derived from your code with some static test data. Please explain what else you need or what is different in your case. In the example, the statically added number in the column header equals the dynamically added VisiblePosition number.

<Grid x:Name="grid1">
    <xd:DataGridControl ItemsSource="{Binding Data}">
        <xd:DataGridControl.Resources>
            <ControlTemplate x:Key="HeaderTemplate" TargetType="{x:Type xd:ColumnManagerCell}">
                <DockPanel>
                    <TextBlock DockPanel.Dock="Top" Text="{TemplateBinding Content}" x:Name="TextContainer"/>
                    <TextBlock Text="{Binding Path=ParentColumn.VisiblePosition,RelativeSource={RelativeSource TemplatedParent}}" Foreground="Red"/>
                </DockPanel>
            </ControlTemplate>
            <Style TargetType="{x:Type xd:ColumnManagerRow}">
                <Setter Property="Background" Value="AliceBlue"/>
                <Setter Property="BorderBrush" Value="Black"/>
                <Setter Property="AllowColumnReorder" Value="False"/>
            </Style>
            <Style TargetType="{x:Type xd:ColumnManagerCell}">
                <Setter Property="Template" Value="{StaticResource HeaderTemplate}"/>
            </Style>
        </xd:DataGridControl.Resources>
    </xd:DataGridControl>
</Grid>

Code behind for data creation

public DataTable Data { get; set; }
private void Window_Loaded(object sender, RoutedEventArgs e)
{
    Data = new DataTable("My Data Table");
    for (int i = 0; i < 100; i++)
    {
        Data.Columns.Add("Column " + i + " Head");
    }
    for (int i = 0; i < 10; i++)
    {
        var row = Data.NewRow();
        for (int j = 0; j < 100; j++)
        {
            row.SetField(j, string.Format("{0},{1}", i, j));
        }
        Data.Rows.Add(row);
    }
    grid1.DataContext = this;
}
grek40
  • 13,113
  • 1
  • 24
  • 50
  • Just to make sure, visible position isn't affected in some way by the virtualization right? – Christo S. Christov Feb 10 '17 at 12:07
  • I need to get the actual index( the index in the model ) – Christo S. Christov Feb 10 '17 at 12:11
  • @Hristo Then explain which kind of index you are talking about. If it's something from the model, then include an index property for the model. – grek40 Feb 10 '17 at 12:21
  • the problem is that there is no way for me to access the model of the column as I'm feeding in a DataTable object as the ItemsSource – Christo S. Christov Feb 10 '17 at 12:22
  • yep, didn't realize that there are two separate indices at the time of writing – Christo S. Christov Feb 10 '17 at 12:22
  • Maybe you can explain what you actually want to archieve. An index that's not related to the visual position is almost certainly a bad candidate to be used for distinct styling. – grek40 Feb 10 '17 at 12:24
  • I have some data which I want to visualize about each column index. The styling isn't distinct for each column, it is the same for all columns. I just want to add one more textblock for each column index that's all :( – Christo S. Christov Feb 10 '17 at 12:27
  • Or maybe a way to disable column virtualization would also be useful – Christo S. Christov Feb 10 '17 at 12:54
  • Virtualization should not be the issue (did you already try the solution?). Column reordering would change the index values, so depending on your needs that might be bad. See my edit for a way to disable it. – grek40 Feb 10 '17 at 16:31
  • didn't work, still get bloated columns e.g when scrolling the text gets mixed – Christo S. Christov Feb 11 '17 at 14:42
  • I think allowing column reorder means to have the ability to grab and put the column in different position – Christo S. Christov Feb 11 '17 at 14:43
  • I just need the actual column index that's all :( – Christo S. Christov Feb 11 '17 at 14:56
  • Maybe you can add a specific example of what you get and what you want. Also consider to just define you columns explicitely, then you won't run into problems of the auto generated columns sort. – grek40 Feb 11 '17 at 18:26
  • grek40 I can't define them explicitly since my data dimensions are dynamic. – Christo S. Christov Feb 11 '17 at 18:27
  • @Hristo added an example, you still didn't explain what's the difference between visible position and the index you are talking of. They are the same for me when columns are not visibly reordered. – grek40 Feb 12 '17 at 11:42
  • The index is the index of the column in the model. The visible index is the index of the column when it is visualized. – Christo S. Christov Feb 16 '17 at 13:11
  • Ok after a huge amount of time I noticed the problem!! The bloody control reuses the data contexts for the controls in the columns which are virtualized. I hate it oficially now. – Christo S. Christov Feb 16 '17 at 15:22
  • @Hristo Now I'm somehow interested... hope you edit it into the question or add an answer (depending on whether you found a solution or just the real problem) – grek40 Feb 16 '17 at 15:23
0

In the end I wasn't able to find a solution so I just used the built in DataGrid. The problem is that I cannot retrieve the actual indices in any way.

Christo S. Christov
  • 2,268
  • 3
  • 32
  • 57