19

I need to bind the Visibility of a DataGridTemplateColumn to a property outside of the DataGrid.ItemsSource,because i need to bind this column in the all the rows to one property inside the ViewModel,but as far as i know you just can bind that to something inside the ItemsSource or you should use ElementStyle and EditingElementStyle I've Already tried this code:

 <DataGridTemplateColumn Header="post" 
                      Visibility="{Binding DataContext.ProjectPostVisibility
                    , RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=MvvmCommonControl:DataGrid}}"/>

And i'm Sure my binding is correct because it works fine when i bind the DataGridCell.Visibility like below:

<DataGridTemplateColumn Header="post">
    <DataGridTemplateColumn.CellStyle>
                        <Style TargetType="DataGridCell">
                            <Setter Property="Visibility" Value="{Binding DataContext.ProjectPostVisibility,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=MvvmCommonControl:DataGrid}}"/>
                        </Style>
                    </DataGridTemplateColumn.CellStyle>
</DataGridTemplateColumn >
2
  • Can you show some code ? Commented Mar 9, 2013 at 12:11
  • @ AbZy:I added some code above.
    – mahboub_mo
    Commented Mar 9, 2013 at 12:16

3 Answers 3

28

Your binding is correct, but it won't work with DataGridTemplateColumn directly because it's not in the visual tree. So it's not inherting DataContext.

You need to bind the DataGridTemplateColumn from code behind. Here is a demo that shows a way of doing it.

1
  • AbZy:Thank you so much.I didn't know that,and it was really interesting!
    – mahboub_mo
    Commented Mar 10, 2013 at 6:53
9

As mentionned in other answers, the column isn't part of the visual/logical tree and doesn't inherit from FrameworkElement meaning it has no DataContext. That's why your binding doesn't work.

However you can add a dummy (collapsed) FrameworkElement at a level where the DataContext is what you're looking for (so taking your example, it'd be at the DataGrid's level), collapse it and use it as the Source of your Binding with the x:Reference markup extension.

Here's an example :

<FrameworkElement x:Name="Proxy" Visibility="Collapsed"/>
<DataGrid>
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="post" 
            Visibility="{Binding DataContext.ProjectPostVisibility, Source={x:Reference Name=Proxy}}"/>
    </DataGrid.Columns>
</DataGrid>
5

Add this setter in the DataGridTemplateColumn.CellStyle and done:

   <Setter Property="Visibility" Value="{Binding DataContext.isVisible, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}"/>

If you need more help look at my example below. I want the Remove button to not be visible at the project level. First you have to make sure you have a isVisible property in your view model:

  private System.Windows.Visibility _isVisible;
    public System.Windows.Visibility isVisible
    {
        get { return _isVisible; }
        set
        {
            if (_isVisible != value)
            {
                _isVisible = value;
                OnPropertyChanged("isVisible");
            }
        }
    }

Then:

  if (isProj == false)
            this.model.isVisible = Visibility.Visible;
        else
            this.model.isVisible = Visibility.Collapsed;

XAML:

<DataGridTemplateColumn  >
       <DataGridTemplateColumn.CellTemplate >
            <DataTemplate >
               <Button x:Name="btnRemove" Content="X">
                 <Button.Style>
                    <Style TargetType="{x:Type Button}">
                         <Setter Property="FontWeight" Value="ExtraBold" />
                         <Setter Property="FontSize" Value="50" />
                     </Style>
                 </Button.Style>
            </Button>
         </DataTemplate>
   </DataGridTemplateColumn.CellTemplate>
   <DataGridTemplateColumn.CellStyle>
        <Style TargetType="{x:Type DataGridCell}">
               <Setter Property="Background"  Value="Red"/>
               <Setter Property="Visibility" Value="{Binding DataContext.isVisible, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}"/>
        </Style>
   </DataGridTemplateColumn.CellStyle>

3
  • 1
    But there needs to be also this (for header text to reflect visible binding): <DataGridTemplateColumn.HeaderStyle> <Style TargetType="DataGridColumnHeader"> <Setter Property="Visibility" Value="{Binding Path=DataContext.isVisible, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}" /> </Style> </DataGridTemplateColumn.HeaderStyle>
    – psulek
    Commented Apr 9, 2018 at 10:45
  • 1
    Thanks. Both the response and the comment from @psulek helped. Commented Nov 18, 2019 at 21:02
  • While this solution seems to be great, be aware that it does not hide the column ifsef, but only it's content.
    – sa.he
    Commented Dec 17, 2019 at 7:44

Not the answer you're looking for? Browse other questions tagged or ask your own question.