2
votes

I am trying to prepare template for DataGridColumnHeader. Template should be really simple.

Attached dependency property csdpp:CalendarProperties.EnumDay should only specific day that DataGridColumnHeader belong to and converter should then just return right label for that day.

If I set AncestorType to DataGridTextColumn (that is what I want) and leave the code like this:

<Style TargetType="DataGridColumnHeader" x:Key="DayHeaderStyle">
        <Setter Property="ContentTemplate">
            <Setter.Value> 
                <DataTemplate>
                    <TextBox Text="{Binding
                    RelativeSource={RelativeSource FindAncestor, AncestorType=DataGridTextColumn}, Mode=OneWay,
                        Path=(csdpp:CalendarProperties.EnumDay),
                    Converter={StaticResource IndexToDayLabelConverter}}"/>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>

nothing happen. Converter is not even getting called.

But if I change code to this:

<Style TargetType="DataGridColumnHeader" x:Key="DayHeaderStyle">
        <Setter Property="ContentTemplate">
            <Setter.Value> 
                <DataTemplate>
                    <TextBox Text="{Binding
                    RelativeSource={RelativeSource FindAncestor, AncestorType=DataGrid}, Mode=OneWay,
                        Path=(csdpp:CalendarProperties.EnumDay),
                    Converter={StaticResource IndexToDayLabelConverter}}"/>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>

(DatagridTextColumn switched by DataGrid, DataGrid has attached property too (below))

Converter is getting called and as value is passed attached property from DataGrid. Why is that working for DataGrid and not for DataGridTextColumn? Please help.

Code with DataGrid and DataGridTextColumn:

<DataGrid Grid.Row="1" Grid.Column="1" 
          x:Name="_shiftDataGrid" 
          ItemsSource="{Binding ElementName=Root, Path=PersonShiftgroupings.ShiftPersons}"
          DataContext="{Binding ElementName=Root, Path=PersonShiftgroupings.ShiftPersons}"
          AutoGenerateColumns="False"
          csdpp:CalendarProperties.EnumDay="Fri">

    <DataGrid.Columns>
        <DataGridTextColumn 
            csdpp:CalendarProperties.EnumDay="Wed"
            HeaderStyle="{StaticResource DayHeaderStyle}">
        </DataGridTextColumn>
    </DataGrid.Columns> 
</DataGrid>

Any help would be appreciated.

2
It's because DataGridColumn is not in the VisualTree of the DataGrid , DataGridColumnHeader are , i'm not sure how to write the binding in this case , it would involve some trial and error could you send me a sample ? here's the Column property in DataGridColumnHeader : msdn.microsoft.com/en-us/library/… - eran otzap

2 Answers

2
votes

Like i stated in my comment above DataGridColumnHeader is in the VisualTree of DataGrid via DataGridColumnHeaderPresenter and not in the VisualTree of DataGridColumn.

You can reach the Column through DataGridColumnHeader's Column property Column

I didn't want to get into your implementation and logic because i'm sure there's a cleaner way of doing what ever it is you need done.

Here's a sample of what you need to get it working :

CS:

  public partial class MainWindow : Window
  {
      public MainWindow()
      {
          InitializeComponent();
          this.DataContext = this;
      }

      public List<SomeItem> MyItems
      {
          get { return new List<SomeItem> { new SomeItem() , new SomeItem() , new SomeItem() , new SomeItem()  };   }
      }

  }

  public class SomeItem
  {
      public int First { get { return 1; } }
      public int Second { get { return 2; } }
      public int Third { get { return 3; } }
      public int Forth { get { return 4; } }
  }



  public static class ASample
  {
      public static string GetMyProperty(DependencyObject obj)
      {
          return (string)obj.GetValue(MyPropertyProperty);
      }

      public static void SetMyProperty(DependencyObject obj, string value)
      {
          obj.SetValue(MyPropertyProperty, value);
      }

      public static readonly DependencyProperty MyPropertyProperty =
        DependencyProperty.RegisterAttached("MyProperty", typeof(string), typeof(ASample));            
  }

  public class ColumnHeaderConverter : IValueConverter
  {
      public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
      {
          if (value == null)
              return string.Empty;

          DataGridColumn c = (DataGridColumn)value;
          string header = ASample.GetMyProperty(c);
          return header;
      }

      public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
      {
          throw new NotImplementedException();
      } 
  }        

XAML :

       <Window.Resources>

    <local:ColumnHeaderConverter x:Key="colConverter"/>

    <Style TargetType="DataGridColumnHeader" x:Key="DayHeaderStyle">
        <Setter Property="ContentTemplate">
            <Setter.Value>
                <DataTemplate>
                    <TextBox Text="{Binding 
              RelativeSource={RelativeSource AncestorType=DataGridColumnHeader}, Mode=OneWay,
                             Path=Column , Converter={StaticResource colConverter} }"/>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>


</Window.Resources>

<Grid>

    <DataGrid AutoGenerateColumns="False" ColumnHeaderStyle="{StaticResource DayHeaderStyle}" 
              ItemsSource="{Binding MyItems}" local:ASample.MyProperty="DataGrid" > 
        <DataGrid.Columns>

            <DataGridTextColumn Binding="{Binding First}" local:ASample.MyProperty="11"/>
            <DataGridTextColumn Binding="{Binding Second}" local:ASample.MyProperty="22"/>
            <DataGridTextColumn Binding="{Binding Third}"  local:ASample.MyProperty="33"/>
            <DataGridTextColumn Binding="{Binding Forth}" local:ASample.MyProperty="44"/>
        </DataGrid.Columns>
    </DataGrid>

</Grid>                      
0
votes

DataGridTextColumn is no ancestor of DataGridColumnHeader