Почему SubItems.Clear () также удаляет атрибут Name? - PullRequest
4 голосов
/ 04 ноября 2010

Я использую WinForms ListView в подробном режиме (.NET 4.0, работает на Windows 7), и у меня есть функция, которая должна очистить подэлементы в определенном элементе. К сожалению, когда я делаю это, это также ясно, имя:

item.Name = "TESTNAME";
item.SubItems.Clear();
MessageBox.Show(item.Name); //shows nothing

В отладчике я отследил его до этого и посмотрел документацию на MSDN , и она бесполезна,

Очистить: удаляет все подэлементы и родительский ListViewItem из коллекции.

За исключением того, что ListViewItem все еще очень там , потому что позже в функции я смогу снова добавить в него подэлементы!

Конечно, мне не нужно:

while(item.SubItems.Count > 0)
{
    item.RemoveAt(0);
}

Я?

Ответы [ 3 ]

4 голосов
/ 04 ноября 2010

К сожалению ListView - странный зверь, и один из его странных углов состоит в том, что его предметы - это просто набор значений, которые нужно показать, по одному на каждый столбец.

Свойство Name просто автоматизирует помещение чего-либо в первый столбец, и, к сожалению, это "что-то" находится в коллекции SubItems.

Это означает, что если вы осмотрите коллекцию SubItems, вы заметите, что в ней уже есть один элемент, и после задания имени элемента вы увидите, что текст этого элемента равен этому имени.

Это код свойства ListViewItem.Name :

public string Name {
    get {
        if (SubItemCount == 0) {
            return string.Empty;
        }
        else {
            return subItems[0].Name;
        }
    }
    set {
        SubItems[0].Name = value;
    }
}

И свойство ListViewSubItem.Name выглядит так:

public string Name {
    get {
        return (name == null) ? "": name;
    }
    set {
        name = value;
        if (owner != null) {
            owner.UpdateSubItems(-1);
        }
    }
}

Таким образом, очистка коллекции SubItems имеет следствие очистки свойств этого первого элемента, как вы обнаружили, в дополнение к удалению всех остальных элементов из коллекции.

На самом деле происходит очистка коллекции, но любая попытка просмотреть коллекцию SubItems, пока она пуста, приведет к созданию новой коллекции с одним элементом со значениями свойств по умолчанию. В приведенном выше примере кода чтение коллекции SubItems будет автоматически назначать коллекцию с одним элементом внутреннему полю, если коллекция еще не существует.

Так что да, вот как это "работает".

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

while (item.SubItems.Count > 1)
    item.SubItems.RemoveAt(1);
3 голосов
/ 04 ноября 2010

С MSDN :

Примечание

Первым подэлементом в ListViewItem.ListViewSubItemCollection всегда является элемент, которому принадлежат подэлементы,При выполнении операций с подэлементами в коллекции обязательно используйте позицию индекса 1 вместо 0, чтобы внести изменения в первый подэлемент.

Таким образом, при очистке коллекции подэлементов очищаются значения для родительского элемента.а также.

0 голосов
/ 11 апреля 2014

Обратите внимание: 1:
ListViewItem.Text (не Name) - это ListViewItem.SubItems[0], , но:
ListViewItem.SubItems.Clear() очищает также ListViewItem.Name!

Итак, если вы используете SubItems.Clear, вам нужно будет восстановить Name и Text (если они вам нужны).

Обратите внимание: 2:
Если вы используете *Key методы (например, ListView.Items.ContainsKey() или ListView.Items.RemoveByKey()) для доступа к элементам (вместо *Index), позаботьтесь о ListViewItem.Name, то есть key, который необходимо передать эти методы ...

Какая умная логика ...

В случае, если кто-либо вынужден или хочет использовать ListView Я обнаружил другую проблему, описанную в вопрос 23007388 .

Поскольку определение всего этого может занять очень много времени, я разместил этот ответ, даже если эта ветка немного устарела.

...