how do I bind RowDetailsTemplate to the bool variable from the ViewModel via commands or a converter?

48 Views Asked by At

I want do smth like that but i dont know how binding RowDetailsVisibilityMode to bool variable from ViewModel in MVVM. RowDetailsVisibility is Collaped when i select row, but if i click on button RowDetailsVisibility == Visability

Events i ignore, because i dont know i do it from command (i change ContentControl from command)

RowDetailsTemplate

I tried Converter, but i doint know how setting it

My RowDetailsTemplate

                <DataGrid.RowDetailsTemplate>
                    <DataTemplate>
                        <Grid>
                            <TextBlock Foreground="White" Margin="16" Text="{Binding ContolPageName, Mode=TwoWay}"/>
                        </Grid>
                    </DataTemplate>
                </DataGrid.RowDetailsTemplate>

Command like that

        public void ExecuteEditDataGridFormatViewCommand(object obj)
        {

            if (!VisabilityRowDetailsTemplate)
            {
                CurrentChildsView = new DataGridFormatViewModel();
                //row.DetailsVisibility = row.DetailsVisibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;
                ContolPageName = "PANEL";
                VisabilityRowDetailsTemplate = true;
            }
            else
            {
                VisabilityRowDetailsTemplate = false;
            }
  
        }

2

There are 2 best solutions below

0
BionicCode On

To show the row details of a DataGrid in an MVVM compliant way you don't need the view model to participate. It doesn't make much sense, because you don't want to show the details based on some data related condition but on the pressing of a button. This is purely view related problem.

You can use routed commands and handle them in the code-behind.

The following example uses a custom routed command. However, you can also choose to use a predefined routed command. The usage remains the same.

MainWindow.xaml.cs
Define the routed command and the command CommandBinding.Executed and the CommandBinding.CanExecute handlers and implement the toggling of the row detail visibility.

partial class MainWindow : Window
{
  // For example, define the command on the MainWindow class
  public static RoutedCommand ShowDetailsCommand { get; } 
    = new RoutedCommand(nameof(ShowDetailsCommand), typeof(MainWindow));

  private void OnExecutedShowRowDetails(object sender, ExecutedRoutedEventArgs e)
  {       
    var dataGrid = (DataGrid)sender;
    var selectedItemContainer = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromItem(dataGrid.SelectedItem);
    var toggleButton = (ToggleButton)e.OriginalSource;
    selectedItemContainer.DetailsVisibility = toggleButton.IsChecked.GetValueOrDefault()
      ? Visibility.Visible 
      : Visibility.Collapsed;
  }

  private void OnCanExecuteShowRowDetails(object sender, CanExecuteRoutedEventArgs e)
    => e.CanExecute = true;
}

MainWindow.xaml
Define a dedicated column that contains a ToggleButton to toggle the visibility of the row's details view.

<DataGrid ItemsSource="{Binding DataGridItems}"
          RowDetailsVisibilityMode="Collapsed">
  <DataGrid.CommandBindings>
    <CommandBinding Command="{x:Static local:MainWindow.ShowDetailsCommand}"
                    Executed="OnExecutedShowRowDetails"
                    CanExecute="OnCanExecuteShowRowDetails" />
  </DataGrid.CommandBindings>

  <DataGrid.Columns>
    <DataGridTemplateColumn Header="Details">
      <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
          <ToggleButton Command="{x:Static local:MainWindow.ShowDetailsCommand}"
                        Content="Show details" />
        </DataTemplate>
      </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
  </DataGrid.Columns>

  <DataGrid.RowDetailsTemplate>
    <DataTemplate DataType="local:DataGridItem">

      <!-- The TwoWay binding on the TextBlock.Text property is pointless -->
      <TextBlock Text="{Binding ContolPageName}" />
    </DataTemplate>
  </DataGrid.RowDetailsTemplate>
</DataGrid>
0
Sir Rufo On

For converting bool to anything I came up with a BooleanToObjectConverter which can handle this.

public class BooleanToObjectConverter : IValueConverter
{
    public object TrueValue { get; set; }
    public object FalseValue { get; set; }

    public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
    {
        return System.Convert.ToBoolean( value ) ? TrueValue : FalseValue;
    }

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

A converter for the RowDetailsVisibilityMode is declared like this

<converters:BooleanToObjectConverter x:Key="BooleanToDataGridRowDetailsVisibilityMode">
    <converters:BooleanToObjectConverter.TrueValue>
        <DataGridRowDetailsVisibilityMode>VisibleWhenSelected</DataGridRowDetailsVisibilityMode>
    </converters:BooleanToObjectConverter.TrueValue>
    <converters:BooleanToObjectConverter.FalseValue>
        <DataGridRowDetailsVisibilityMode>Collapsed</DataGridRowDetailsVisibilityMode>
    </converters:BooleanToObjectConverter.FalseValue>
</converters:BooleanToObjectConverter>

and used like

<DataGrid ...
          RowDetailsVisibilityMode="{Binding VisabilityRowDetailsTemplate, 
                                     Converter={StaticResource BooleanToDataGridRowDetailsVisibilityMode}}">
   ...
</DataGrid>