views:

143

answers:

0

I have an issue with hiding rows in a DataGrid. I do this by creating a new DataGridRow template which has a DataTrigger bound to a property on the objects in ItemsSource. The trigger sets the Visibility of the border of the row to Collapsed if the IsVisible property on the model object is false and vice-versa.

If I set one row's IsVisible to false, the DataGrid does not resize to take account of the new "size" of the grid. If I set two row's IsVisible to false, the DataGrid DOES resize correctly.

Here's sample code to paste into a new WPF app:

--- MainWindow.xaml ----

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Primitives="clr-namespace:System.Windows.Controls.Primitives;assembly=PresentationFramework"
    Title="MainWindow" Height="350" Width="525">
  <Window.Resources>
    <Style x:Key="{x:Type DataGridRow}" TargetType="{x:Type DataGridRow}">
      <Setter Property="SnapsToDevicePixels" Value="true"/>
      <Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
      <Setter Property="ValidationErrorTemplate">
        <Setter.Value>
          <ControlTemplate>
            <TextBlock Margin="2,0,0,0" VerticalAlignment="Center" Foreground="Red" Text="!" />
          </ControlTemplate>
        </Setter.Value>
      </Setter>
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="{x:Type DataGridRow}">
            <Border x:Name="DGR_Border"
                  Background="{TemplateBinding Background}"
                  BorderBrush="{TemplateBinding BorderBrush}"
                  BorderThickness="{TemplateBinding BorderThickness}"
                  SnapsToDevicePixels="True">
              <Primitives:SelectiveScrollingGrid>
                <Grid.ColumnDefinitions>
                  <ColumnDefinition Width="Auto"/>
                  <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                  <RowDefinition Height="*"/>
                  <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Primitives:DataGridCellsPresenter
                    Grid.Column="1"
                    ItemsPanel="{TemplateBinding ItemsPanel}"
                    SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                <DataGridDetailsPresenter
                    SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=AreRowDetailsFrozen, Converter={x:Static DataGrid.RowDetailsScrollingConverter}, ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical}}"
                    Grid.Column="1" Grid.Row="1"
                    Visibility="{TemplateBinding DetailsVisibility}" />
                <DataGridRowHeader 
                    SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical" Grid.RowSpan="2"
                    Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=HeadersVisibility, Converter={x:Static DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static DataGridHeadersVisibility.Row}}"/>
              </Primitives:SelectiveScrollingGrid>
            </Border>
            <ControlTemplate.Triggers>
              <DataTrigger Binding="{Binding IsVisible,UpdateSourceTrigger=PropertyChanged}" Value="False">
                <Setter TargetName="DGR_Border" Property="Visibility" Value="Collapsed"/>
              </DataTrigger>
            </ControlTemplate.Triggers>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
  </Window.Resources>
  <StackPanel>
    <DataGrid x:Name="dg" AutoGenerateColumns="False" CanUserAddRows="False">
      <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding Name}" />
      </DataGrid.Columns>
    </DataGrid>
    <StackPanel>
      <Button Content="Modify" Click="Button_Click" />
      <Button Content="Modify 2" Click="Button_Click_1" />
    </StackPanel>
  </StackPanel>
</Window>

--- MainWindow.xaml.cs ----

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;

namespace WpfApplication1
{
  /// <summary>
  /// Interaction logic for MainWindow.xaml
  /// </summary>
  public partial class MainWindow : Window
  {
    ObservableCollection<Model> model;

    public MainWindow()
    {
      InitializeComponent();

      model = new ObservableCollection<Model>();
      model.Add(new Model() { Name = "Matthew" });
      model.Add(new Model() { Name = "Mark" });
      model.Add(new Model() { Name = "Luke" });
      model.Add(new Model() { Name = "John" });

      dg.ItemsSource = model;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
      if (model[3].IsVisible)
        model[3].IsVisible = false;  
      else
        model[3].IsVisible = true;  
    }

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
      if (model[2].IsVisible)
      {
        model[2].IsVisible = false;
        model[3].IsVisible = false;
      }
      else
      {
        model[2].IsVisible = true;
        model[3].IsVisible = true;
      }
    }
  }

  class Model : INotifyPropertyChanged
  {
    public string Name { get; set; }

    bool _isVisible = true;
    public bool IsVisible
    {
      get { return _isVisible; }
      set
      {
        if (_isVisible != value)
        {
          _isVisible = value;
          OnPropertyChanged("IsVisible");
        }
      }
    }

    void OnPropertyChanged(string pName)
    {
      PropertyChangedEventHandler eh = this.PropertyChanged;
      if (eh != null)
        eh(this, new PropertyChangedEventArgs(pName));
    }

    public event PropertyChangedEventHandler PropertyChanged;

  }
}

If anyone has any ideas what is going here, it would be greatly appreciated!

Thanks,

Stephen