Событие изменения размера столбца DataGrid в WPF Toolkit

Я использую WPF Toolkit Datagrid в одном из приложений, над которыми я работаю. Я хочу сохранить ширину столбца и displayindex в качестве предпочтений пользователя. Я добился этого для столбца displayindex, но для изменения размера я не смог найти ни одного события в сетке данных, которое сработает после изменения размера столбца. Я пробовал событие «SizeChanged», которое, как мне кажется, запускается только тогда, когда оно изначально вычисляет размер, и это тоже для всей таблицы данных, а не для отдельных столбцов.
Любое альтернативное решение или если кто-то знает о событии ?


person Pravin    schedule 25.10.2010    source источник


Ответы (4)


взято из... :

http://forums.silverlight.net/post/602788.aspx

после нагрузки:

    PropertyDescriptor pd = DependencyPropertyDescriptor
                             .FromProperty(DataGridColumn.ActualWidthProperty,
                                           typeof(DataGridColumn));

        foreach (DataGridColumn column in Columns) {
                //Add a listener for this column's width
                pd.AddValueChanged(column, 
                                   new EventHandler(ColumnWidthPropertyChanged));
        }

2 метода:

    private bool _columnWidthChanging;
    private bool _handlerAdded;
    private void ColumnWidthPropertyChanged(object sender, EventArgs e)
    {
        // listen for when the mouse is released
        _columnWidthChanging = true;
        if (!_handlerAdded && sender != null)
        {
            _handlerAdded = true;  /* only add this once */
            Mouse.AddPreviewMouseUpHandler(this, BaseDataGrid_MouseLeftButtonUp);
        }
    }

    void BaseDataGrid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        if (_columnWidthChanging) {
            _columnWidthChanging = false;
          // save settings, etc

        }

        if(_handlerAdded)  /* remove the handler we added earlier */
        {
             _handlerAdded = false;
             Mouse.RemovePreviewMouseUpHandler(this, BaseDataGrid_MouseLeftButtonUp);
        }
    }

ColumnWidthPropertyChanged срабатывает постоянно, пока пользователь перемещает ширину. Добавление обработчика PreviewMouseUp позволяет обрабатывать, когда пользователь закончит.

person J...    schedule 09.12.2011
comment
Это не сработает, если мы используем двойной щелчок. Двойной щелчок устанавливает автоматическую ширину столбца. - person Rover; 24.05.2012
comment
@Rover ... но при двойном щелчке легко поймать событие. Я не понимаю, в чем проблема. - person J...; 24.05.2012
comment
Одна проблема в том, что вы добавляете много обработчиков событий. - person stefan; 03.06.2016
comment
тогда как получить новую ширину столбца? - person Carlos Liu; 27.06.2017
comment
Это вызывает ад утечки памяти. Также событие Mouse up будет запускаться тысячи раз. - person Mateusz Myślak; 03.02.2020
comment
@ MateuszMyślak Ну, это старый вопрос ... в любом случае, я отредактировал код. Довольно просто добавить обработчик только один раз, а потом удалить. - person J...; 03.02.2020
comment
@J ... Тем не менее, AddValueChanged может привести к серьезным утечкам памяти. - person Mateusz Myślak; 04.02.2020
comment
@ MateuszMyślak Ну, очевидно, вам также нужно удалить обработчики. Я не показывал этот код, но мы можем предположить, что часть очевидна. Если вы говорите не об этом, объясните, пожалуйста, откуда взялась эта утечка памяти. - person J...; 04.02.2020
comment
@J ... Это не так очевидно. Это не стандартный обработчик событий, который в некоторых случаях можно игнорировать. Это обработчик событий объекта, хранящегося в статическом кэше, который никогда не будет собираться сборщиком мусора. - person Mateusz Myślak; 05.02.2020

Макет обновлен?

Я работаю в Silverlight, и сетка обновляется / обновляется каждую секунду.

Я использую метод LayoutUpdated, который срабатывает при каждом обновлении макета.

Вы можете вести словарь ширины столбцов и проверять дельты. Тогда вы узнаете, какие столбцы изменились.

foreach (DataGridColumn column in dataGrid1.Columns)
{
    // check for changes...
    // save the column.Width property to a dictionary...
}
person arachnode.net    schedule 03.10.2012

Вы можете попробовать расширить DataGrid, а затем реализовать NotifyPropertyChange событие. Что-то вроде этого:

class MyDataGrid : DataGrid, INotifyPropertyChanged
{
    private DataGridLength _columnWidth;
    public DataGridLength ColumnWidth
    {
        get { return _columnWidth; }
        set
        {
            _columnWidth = value;
            NotifyPropertyChanged("ColumnWidth");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(String propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Оттуда вы можете добавить к обработчику delagate, чтобы он делал все, что вы хотите. Что-то типа:

MyDataGrid dataGrid;
//init grid, do stuff

dataGrid.PropertyChanged += new PropertyChangedEventHandler(ColumnWidthChanged);
//ColumnWidthChanged will be a method you define

Теперь, когда у вас есть delagate, вы можете определить, что вы хотите, чтобы произошло при изменении ширины столбца:

private void ColumnWidthChanged(object sender, PropertyChangedEventArgs args)
{
    if(args.PropertyName.Equals("ColumnWidth"))
    {
        //Do stuff now that the width is changed
    }
}

Вы заметите, что я проверяю, какое свойство было изменено. Я настроил его так, что вы можете расширять другие свойства, а также создавать обработчики для их изменения. Если вам нужно более одного обработчика, вероятно, лучше всего будет создать метод DataGridPropertyChanged, который будет включать, какое свойство было изменено. Затем он вызовет соответствующий метод (например, ColumnWidthChanged) для каждого изменяемого свойства. Таким образом, вам не нужно будет проверять, что каждый обработчик изменяет только одно свойство.

Вы не указали язык, поэтому я переназначил его на C #. Однако его должно быть достаточно просто перенести на VB, если вы его используете.

Надеюсь это поможет!

person Chad La Guardia    schedule 04.08.2011
comment
Это на самом деле не помогает, потому что у вас есть только одна ширина столбца, и ваше событие будет вызвано только в том случае, если размер столбца был изменен в коде, что вы все равно можете перехватить. - person MikeKulls; 25.11.2011

Я предполагаю, что вы хотите сохранить ширину столбцов, чтобы при следующем запуске приложения те же значения ширины столбцов использовались для создания сетки данных.

В этом случае альтернативой является сохранение ширины столбцов (и индексов) при закрытии приложения, что также будет более эффективным, чем сохранение ширины при каждом изменении размера столбца.

В зависимости от того, как структурировано ваше приложение, должно работать что-то вроде этого ...

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
  foreach (DataGridColumn column in dataGrid1.Columns)
  {
    // save the column.Width property to a user setting/file/registry/etc...
    // optionally save the displayindex as well...
  }
} 
person JayP    schedule 05.12.2011
comment
Привет, не могли бы вы подсказать мне, как скопировать значение из c # в xaml? Я пробовал это: Dictionary ‹строка, DataGridLength› list = new Dictionary ‹строка, DataGridLength› (); foreach (столбец DataGridColumn в DataGridView.Columns) {DataGridLength x = column.Width; list.Add (column.Header.ToString (), x); } - person user1850936; 27.11.2014