Сортировать столбец DataGridView типа Image

1

По умолчанию изображение DataGridViewColumn.ValueType нельзя сортировать.
Это понятно, но мои изображения могут быть отсортированы логически.
Я показываю одно из трех изображений в зависимости от определенного состояния (отметка Check, X или Question mark).

Вопрос: Как мне сортировать столбец изображений?

Этот вопрос: форма окна С#. DataTable с полем "Изображение". Сортировка приближается, однако используется DataTable, а не DataGridView, и, что более важно, я ограничен.NET 2, у которого нет Linq.

Этот вопрос: как создать сопоставимое изображение, вероятно, лучшее решение, но использует Func, который доступен только с.NET 3.5.

Другим аспектом этого является то, что я использую BindingList.
В частности, этот SortableBindingList.

Теги:
sorting
image
datagridview
.net-2.0

1 ответ

2
Лучший ответ

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

= 1
? = 2
= 3

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

Изображение 174551

Код:

namespace SortImagesInDGV
{
    public partial class Form1 : Form
    {
        SortableBindingList<CustomObject> mySortableBindingList;
        Image C32 = SortImagesInDGV.Properties.Resources.C_32.ToBitmap();
        Image X32 = SortImagesInDGV.Properties.Resources.X_32.ToBitmap();
        Image Q32 = SortImagesInDGV.Properties.Resources.Q_32.ToBitmap();
        // used to keep track of sort direction
        bool SortingFlipFlop = true;

        public Form1()
        {
            InitializeComponent();
            mySortableBindingList = new SortableBindingList<CustomObject>();
            mySortableBindingList.Add(new CustomObject("c mark", 1, C32));
            mySortableBindingList.Add(new CustomObject("x mark", 3, X32));
            mySortableBindingList.Add(new CustomObject("q mark", 2, Q32));
            mySortableBindingList.Add(new CustomObject("cross mark", 3, X32));
            mySortableBindingList.Add(new CustomObject("check mark", 1, C32));
            mySortableBindingList.Add(new CustomObject("question mark", 2, Q32));

            dataGridView1.DataSource = mySortableBindingList;
            // Sorting image with this event
            dataGridView1.ColumnHeaderMouseClick += new DataGridViewCellMouseEventHandler(gridViewData_ColumnHeaderMouseClick);           
            // Must explicitly set the image column as sortable
            dataGridView1.Columns["AnImage"].SortMode = DataGridViewColumnSortMode.Automatic;
            // Hide the number "key" column
            dataGridView1.Columns["ANumber"].Visible = false;
        }

            void gridViewData_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
            {
                if (dataGridView1.Columns[e.ColumnIndex].Name == "AnImage")
                {
                    // Change the sort direction each time the column header for image is clicked
                    ListSortDirection Direction;
                    if (SortingFlipFlop) { Direction = ListSortDirection.Ascending; SortingFlipFlop = false; }
                    else { Direction = ListSortDirection.Descending; SortingFlipFlop = true; }
                    // Perform the sort on the number / 'key' column
                    dataGridView1.Sort(dataGridView1.Columns["ANumber"], Direction);
                    // Show the sorting glyph in the image column
                    if (Direction == ListSortDirection.Ascending)
                    { dataGridView1.Columns["AnImage"].HeaderCell.SortGlyphDirection = SortOrder.Descending; }
                    else if (Direction == ListSortDirection.Descending)
                    { dataGridView1.Columns["AnImage"].HeaderCell.SortGlyphDirection = SortOrder.Ascending; }
                    else { dataGridView1.Columns["AnImage"].HeaderCell.SortGlyphDirection = SortOrder.None; }
                }
            }
    }

Класс объекта:

    public class CustomObject : INotifyPropertyChanged
    {
        private string _someText; private int _aNumber;  private Image _anImage;
        public event PropertyChangedEventHandler PropertyChanged;

        public CustomObject(string sometext, int anumber, Image animage)
        { _someText = sometext; _aNumber = anumber; _anImage = animage; }

        [DisplayName("Some Text")]
        public string SomeText { get { return _someText; }
            set { _someText = value; this.NotifyPropertyChanged("SomeText"); }
        }
        public int ANumber { get { return _aNumber; }
            set { _aNumber = value; this.NotifyPropertyChanged("ANumber"); }
        }
        [DisplayName("My Image")]
        public Image AnImage { get { return _anImage; }
            set { _anImage = value; this.NotifyPropertyChanged("AnImage"); }
        }

        private void NotifyPropertyChanged(string name)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }

SortableBindingList

    /// <summary>
    /// Provides a generic collection that supports data binding and additionally supports sorting.
    /// See http://msdn.microsoft.com/en-us/library/ms993236.aspx
    /// If the elements are IComparable it uses that; otherwise compares the ToString()
    /// </summary>
    /// <typeparam name="T">The type of elements in the list.</typeparam>
    public class SortableBindingList<T> : BindingList<T> where T : class
    {
        private bool _isSorted;
        private ListSortDirection _sortDirection = ListSortDirection.Ascending;
        private PropertyDescriptor _sortProperty;

        /// <summary>
        /// Initializes a new instance of the <see cref="SortableBindingList{T}"/> class. </summary>
        public SortableBindingList() { }

        /// <summary>
        /// Initializes a new instance of the <see cref="SortableBindingList{T}"/> class. </summary>
        /// <param name="list">An <see cref="T:System.Collections.Generic.IList'1" /> of items to be contained in the <see cref="T:System.ComponentModel.BindingList'1" />.</param>
        public SortableBindingList(IList<T> list) : base(list) { }

        /// <summary>
        /// Gets a value indicating whether the list supports sorting. </summary>
        protected override bool SupportsSortingCore { get { return true; } }

        /// <summary>
        /// Gets a value indicating whether the list is sorted. </summary>
        protected override bool IsSortedCore { get { return _isSorted; } }

        /// <summary>
        /// Gets the direction the list is sorted. </summary>
        protected override ListSortDirection SortDirectionCore { get { return _sortDirection; } }

        public ListSortDirection mySortDirection { get { return _sortDirection; } }

        /// <summary>
        /// Gets the property descriptor that is used for sorting the list if sorting is implemented in a derived class; otherwise, returns null </summary>
        protected override PropertyDescriptor SortPropertyCore { get { return _sortProperty; } }

        /// <summary>
        /// Removes any sort applied with ApplySortCore if sorting is implemented </summary>
        protected override void RemoveSortCore() {
            _sortDirection = ListSortDirection.Ascending; _sortProperty = null; _isSorted = false;
        }

        /// <summary>
        /// Sorts the items if overridden in a derived class </summary>
        protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction) {
            _sortProperty = prop; _sortDirection = direction;

            List<T> list = Items as List<T>;
            if (list == null) return;
            list.Sort(Compare); _isSorted = true;
            //fire an event that the list has been changed.
            OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }

        private int Compare(T lhs, T rhs) {
            var result = OnComparison(lhs, rhs);
            //invert if descending
            if (_sortDirection == ListSortDirection.Descending) result = -result;
            return result;
        }

        private int OnComparison(T lhs, T rhs) {
            object lhsValue = null; if (lhs != null) { lhsValue = _sortProperty.GetValue(lhs); }
            object rhsValue = null; if (rhs != null) { rhsValue = _sortProperty.GetValue(rhs); }
            if (lhsValue == null) { return (rhsValue == null) ? 0 : -1; }
            if (rhsValue == null) { return 1; } //first has value, second doesn't 
            if (lhsValue is IComparable) { return ((IComparable)lhsValue).CompareTo(rhsValue); }
            if (lhsValue.Equals(rhsValue)) { return 0; } //both are the same
            return lhsValue.ToString().CompareTo(rhsValue.ToString()); //not comparable, compare ToString
        }
    }
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню