Home > Software engineering >  Boolean binding, decide to rotate DataGrid or not
Boolean binding, decide to rotate DataGrid or not

Time:08-12

In my code I have a DataGrid that I want to rotate for certain cases. Basically "rotating" just means switching the view mode of the DataGrid (displaying columns horizontally or vertically).

The idea is to have a boolean variable coming from an interface. Depending on that, I want to activate/deactivate the transformed view. I think I will need like a converter or something..?

I just copy-pasted this code from another stackoverflow-question. I played a bit with it but I cannot answer questions to. I know, that following values HAVE TO be changed when rotating or not:

  • RotateTransform Angle="-90"
  • MatrixTransform Matrix="-1 0 0 1 0 0"
  • RotateTransform Angle="-90"
  • ScaleTransform ScaleX="1" ScaleY="-1"
  • RotateTransform Angle="-90"
  • ScaleTransform ScaleX="1" ScaleY="-1"

This is my XAML:

<DataGrid ItemsSource="{Binding Path=CurrentTable.DefaultView, IsAsync=True}" AutoGenerateColumns="True" AutoGeneratingColumn="DataGrid_AutoGeneratingColumn"   
          SelectedItem="{Binding SelectedItem}" IsReadOnly="False">
  <DataGrid.LayoutTransform>
    <TransformGroup>
      <RotateTransform Angle="90"/>
      <MatrixTransform Matrix="-1 0 0 1 0 0" />
    </TransformGroup>
  </DataGrid.LayoutTransform>
  <DataGrid.ColumnHeaderStyle>
    <Style TargetType="{x:Type DataGridColumnHeader}"
          BasedOn="{StaticResource {x:Type DataGridColumnHeader}}">
      <Setter Property="LayoutTransform">
        <Setter.Value>
          <TransformGroup>
            <RotateTransform Angle="-90"/>
            <ScaleTransform ScaleX="1" ScaleY="-1" />
          </TransformGroup>
        </Setter.Value>
      </Setter>
    </Style>
  </DataGrid.ColumnHeaderStyle>
  <DataGrid.CellStyle>
    <Style TargetType="DataGridCell">
      <Setter Property="LayoutTransform">
        <Setter.Value>
          <TransformGroup>
            <RotateTransform Angle="-90"/>
            <ScaleTransform ScaleX="1" ScaleY="-1" />
          </TransformGroup>
        </Setter.Value>
      </Setter>
    </Style>
  </DataGrid.CellStyle>
</DataGrid>

Could you help me? I really do not know, where to start and what to start with.


Edit 1: With big help of @thatguy I was able to rotate my DataGrid. I wonder how I can change the weird sizes of the cells after being rotated. An example of my code.

Before rotating:

the cells have normal size

After rotating:

the size of the cells is way too big

This is the definition of my DataGrid:

CodePudding user response:

You do not need a converter, it can all be done in the style using triggers. Suppose you created a bool property named IsCertainCase in your view model which must implement the INotifyPropertyChanged interface to notify bindings to update their value, otherwise a changed value in the view model will not be reflected in the user interface.

public class MyViewModel : INotifyPropertyChanged
{
      private bool _isCertainCase;
   public bool IsCertainCase
   {
      get => _isCertainCase;
      set
      {
         if (_isCertainCase == value)
            return;
   
         _isCertainCase = value;
         OnPropertyChanged();
      }
   }

   public event PropertyChangedEventHandler PropertyChanged;
   
   protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
   {
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
   }

   // ...other code.
}

Then you can create a Style for the DataGrid. Note that it needs to extend the default style for DataGrid, otherwise its visual appearance or behavior might be different. That is what the BasedOn property is for.

A DataTrigger is used to bind the IsCertainCase property and check whether it is True or not.

Represents a trigger that applies property values or performs actions when the bound data meets a specified condition.

In case it is, the LayoutTransform is applied. The other styles work just the same, with one major difference. Their DataContext is different than the DataContext of the DataGrid. Consequently, a binding to IsCertainCase would fail. In this case we use a RelativeSource which refers to a parent element of a certain type specified with AncestorType, here DataGrid. As path, we specify its DataContext and on that the property IsCertainCase. Now we bind the same data as on the DataGrid style.

<DataGrid ItemsSource="{Binding Path=CurrentTable.DefaultView, IsAsync=True}" AutoGenerateColumns="True" AutoGeneratingColumn="DataGrid_AutoGeneratingColumn"   
          SelectedItem="{Binding SelectedItem}" IsReadOnly="False">
   <DataGrid.Style>
      <Style TargetType="{x:Type DataGrid}"
             BasedOn="{StaticResource {x:Type DataGrid}}">
         <Style.Triggers>
            <DataTrigger Binding="{Binding IsCertainCase}" Value="True">
               <Setter Property="LayoutTransform">
                  <Setter.Value>
                     <TransformGroup>
                        <RotateTransform Angle="90"/>
                        <MatrixTransform Matrix="-1 0 0 1 0 0" />
                     </TransformGroup>
                  </Setter.Value>
               </Setter>
            </DataTrigger>
         </Style.Triggers>
      </Style>
   </DataGrid.Style>
   <DataGrid.ColumnHeaderStyle>
      <Style TargetType="{x:Type DataGridColumnHeader}"
             BasedOn="{StaticResource {x:Type DataGridColumnHeader}}">
         <Style.Triggers>
            <DataTrigger Binding="{Binding DataContext.IsCertainCase, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" Value="True">
               <Setter Property="LayoutTransform">
                  <Setter.Value>
                     <TransformGroup>
                        <RotateTransform Angle="-90"/>
                        <ScaleTransform ScaleX="1" ScaleY="-1" />
                     </TransformGroup>
                  </Setter.Value>
               </Setter>
            </DataTrigger>
         </Style.Triggers>
      </Style>
   </DataGrid.ColumnHeaderStyle>
   <DataGrid.CellStyle>
      <Style TargetType="DataGridCell"
             BasedOn="{StaticResource {x:Type DataGridCell}}">
         <Style.Triggers>
            <DataTrigger Binding="{Binding DataContext.IsCertainCase, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" Value="True">
               <Setter Property="LayoutTransform">
                  <Setter.Value>
                     <TransformGroup>
                        <RotateTransform Angle="-90"/>
                        <ScaleTransform ScaleX="1" ScaleY="-1" />
                     </TransformGroup>
                  </Setter.Value>
               </Setter>
            </DataTrigger>
         </Style.Triggers>
      </Style>
   </DataGrid.CellStyle>
</DataGrid>
  • Related