Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bind DataGridTemplateColumn.Visibility to a property outside of DataGrid.ItemsSource?

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 >
like image 948
mahboub_mo Avatar asked Mar 09 '13 12:03

mahboub_mo


People also ask

Is it possible to bind to datagridtemplatecolumn in visual tree?

But this binding in DataGridTemplateColumn will not work as DataGrid Column is not a part of Visual Tree. So, I created a Class Called BindingProxy as follows: But still the binding is not successful. Can anybody ssuggest a good solution?

Why can't I bind DataGrid headers of columns with the default binding?

The columns of DataGrid.Columns do not inherit the DataContext of the DataGrid element, so you cannot easily bind DataGrid Headers of Columns with the default binding expression. This is caused by not inheriting from FrameworkElement.

How to get Column Visibility in bindingproxy?

Data dependency property of BindingProxy holds textBlock Visibility, so you need to bind with it. and your column visibility will work fine. Thanks for contributing an answer to Stack Overflow!

Does datagridtextcolumn inherit DataContext of DataGrid?

Notable quote: “First of all DataGridTextColumn or any other supported dataGrid columns doesn’t lie in Visual tree of DataGrid. Hence, by default it doesn’t inherit DataContext of DataGrid. But, it works for Binding DP only and for not other DP’s on DataGridColumn.”


3 Answers

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.

like image 144
Abdusalam Ben Haj Avatar answered Oct 09 '22 11:10

Abdusalam Ben Haj


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>

like image 31
Bianca Kalman Avatar answered Oct 09 '22 11:10

Bianca Kalman


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>
like image 5
nalka Avatar answered Oct 09 '22 10:10

nalka