折叠行时动态调整数据网格列的大小

时间:2018-04-16 13:47:27

标签: c# wpf xaml datagrid

我有一个DataGrid控件,dgChangesMade,ItemsSource = ObservableCollection<CheckinPath>

第一列dgPath是一个DataGridTemplateColumn,由

组成
  • 复选框
  • TextBlock的。转换器为后者返回相对路径。 数据网格行的可见性绑定到IsVisible属性。

除了DataGrid控件之外,我还有一个CheckBox控件:

  • IsChecked事件绑定到布尔属性IsChecked。 setter设置绑定到DataGrid的项源的对象的IsVisible属性。因此,当选中(取消)复选框时,将折叠/显示数据网格行。
  • SourceUpdated事件绑定到CheckBox_SourceUpdated

斯科特在another thread中指出:

  

DataGrid将增加列大小以适应数据   更长,但它不会自动减少列大小时   数据长度减少

所以在CheckBox_SourceUpdated事件中我

  1. 将列宽设置为0
  2. 强制DataGrid的更新布局
  3. 将列宽设置为自动
  4. 不幸的是,没有帮助。 当(取消)检查复选框控件时,列宽会在需要时增加(请参见屏幕截图中的2),但不会根据datagrid列中的数据长度自动减小(请参见屏幕截图中的3,3显示相同)内容为1)。

    有什么想法吗?

    截图 enter image description here

    XAML

    <DataGrid Name='dgChangesMade' Width='Auto' ItemsSource="{Binding Path=ChangesMade}">
        <DataGrid.Resources>
            <DataGridTemplateColumn Width='Auto' x:Key='dgPath' Header='Path' IsReadOnly='True' x:Shared='False'>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <StackPanel Orientation='Horizontal' VerticalAlignment='Center'>
                        <CheckBox IsChecked='{Binding IsChecked, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}'>
                        <TextBlock Text='{Binding Converter={StaticResource CheckinPathConverter}, ConverterParameter="Path"}' />
                        </StackPanel>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
    
            <Style x:Key='dgShowHideRow' TargetType='DataGridRow'>
                <Setter Property='Visibility' Value='{Binding IsVisible, Converter={StaticResource BoolToVisibilityConverter}, ConverterParameter="Collapsed", Mode=TwoWay}' />
            </Style>
    
        <DataGrid.Columns>
            <StaticResource ResourceKey='dgPath' />
            <StaticResource ResourceKey='dgStatus' />
            <StaticResource ResourceKey='dgLock' />
        </DataGrid.Columns>
        <DataGrid.ItemContainerStyle>
            <StaticResource ResourceKey='dgShowHideRow' />
        </DataGrid.ItemContainerStyle>
    </DataGrid>
    <!-- Setter of this checkbox sets the IsVisible property of the datagrid bound objects -->
    <CheckBox IsChecked='{Binding IsChecked, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}' SourceUpdated='CheckBox_SourceUpdated'/>
    

    代码

    private void CheckBox_SourceUpdated(object sender, DataTransferEventArgs e)
    {
        foreach (var c in dgChangesMade.Columns)
            c.Width = 0;
    
        dgChangesMade.UpdateLayout();
        foreach (var c in dgChangesMade.Columns)
            c.Width = new DataGridLength(1, DataGridLengthUnitType.Auto);
    }
    

    模型

    public class CheckinPath : ViewModelBase
    {
        private bool _isVisible;
        public bool IsVisible
        {
            get { return _isVisible; }
            set
            {
                if (_isVisible != value)
                {
                    _isVisible = value;
                    RaisePropertyChanged(nameof(IsVisible));
                }
            }
        }  
    }
    

1 个答案:

答案 0 :(得分:0)

我解决了这个问题。

  1. 现在绑定到ObservableCollection,而不是将datagrid itemsource绑定到CollectionView。 这样,可以使用CollectionViewSource Filter属性显示/隐藏数据网格中的行。 过滤发生在ViewModel。
  2. 过滤CollectionView后,将重置数据网格的列宽。 因为数据网格是一个控件,所以重置发生在视图后面的代码中(使用来自MVVM Light Toolkit的Messenger)
  3. <强> XAML

    <DataGrid x:Name='dg'
                ItemsSource='{Binding ChangesMadeView}'
                AutoGenerateColumns='False'
                IsReadOnly='True' .../>
    <CheckBox IsChecked='{Binding IsChecked, UpdateSourceTrigger=PropertyChanged}' .../>
    

    幕后代码

    public partial class TestWindow : Window
    {
        public static readonly Guid Token = new Guid();
        public TestWindow()
        {
            InitializeComponent();
            Messenger.Default.Register<NotificationMessage>(this, Token, ResetColumnWidth);
        }
    
        private void ResetColumnWidth(NotificationMessage notMessage)
        {
            if (notMessage.Notification == "ResetColumnWidth")
            {
                foreach (DataGridColumn c in dg.Columns)
                {
                    c.Width = 0;
                    c.Width = DataGridLength.Auto;
                }
            }
        }
    }
    

    <强>视图模型

    private IList<CheckinPath> _changesMade = new List<CheckinPath>();
    public ICollectionView ChangesMadeView { get; private set; }
    
    public TestViewModel()
    {
        LoadData(); //Loads data for _changesMade
        ChangesMadeView = CollectionViewSource.GetDefaultView(_changesMade);
    }
    
    private bool _isChecked;
    
    public bool IsChecked
    {
        get { return _isChecked; }
        set
        {
            if (_isChecked != value)
            {
                _isChecked = value;
                RaisePropertyChanged(nameof(IsChecked));
                ChangesMadeView.Filter = checkinPath => { //do logic for filtering. Returns true or false ;};
                Messenger.Default.Send(new NotificationMessage("ResetColumnWidth"), TestWindow.Token); //notify the code behind of the view
            };
        }
    }