2013-02-15 4 views
1

Есть ли кто-нибудь, кто успешно получил флажки tri-state, корректно работающие в TreeListView, без использования свойства в объекте модели для хранения контрольного состояния?ObjectListView - TreeListView Auto TriStateChecking

Так, например, проверяется узел. Все его дети (и дети детей и т. Д.) Должны быть проверены, а затем все его родители/дедушки и бабушки должны быть проверены в соответствии с его братьями и сестрами CheckStates.

Я пробовал несколько методов, но каждый путь получаю ArgumentOutOfRange/ArgumentException в классе TreeListView. Это включает в себя следующее:

  • Сохранение всех узлов CheckStates в словарь и с использованием в качестве поиска с CheckStateGetter события
  • Рекурсивный вызов функции, когда элементы CheckState изменения (и обеспечивающие последующие события ItemCheck игнорируются в то время как программно изменение CheckStates)
  • Вызов функции для определения непосредственных дочерних/родительских состояний и разрешения TreeListView на событие ItemChecked для каждого из затронутых узлов.

Я постоянно получаю ошибки из следующих функций (в TreeListView.cs):

  • GetNthItem()
  • GetChildren() - а затем расширение/разрушаясь Шилд в GUI
  • ProcessLButtonDown()

Если кто-то там был успешным, я все уши.

ответ

1

У меня также возникли проблемы с TreeListView и нашла проблему в функциях GetChildren().

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

Оригинальный метод:

public virtual IEnumerable GetChildren(Object model) { 
     Branch br = this.TreeModel.GetBranch(model); 
     if (br == null || !br.CanExpand) 
      return new ArrayList(); 

     if (!br.IsExpanded) // THIS IS THE PROBLEM 
      br.Expand(); 

     return br.Children; 
    } 

Фиксированный метод:

public virtual IEnumerable GetChildren(Object model) { 
     Branch br = this.TreeModel.GetBranch(model); 
     if (br == null || !br.CanExpand) 
      return new ArrayList(); 

     br.FetchChildren(); 

     return br.Children; 
    } 

Может быть, это решает по крайней мере, некоторые из ваших проблем.

+1

Большое спасибо, я только что нашел эту проблему сам, однако я изменил линию в questi on if if (br.CanExpand) br.FetchChildren(); '. Вы заметили какие-либо побочные эффекты от этой модификации? Тем не менее, он выглядит корректно - это не изменяет свойство «Expanded» Branch, которое вызывает все проблемы :) +1 независимо от того, как искать источник (что я должен был сделать раньше!) – Simon

+0

Изменение кода по-видимому, не вызывает какого-либо побочного эффекта, насколько я могу судить. TreeListView довольно плохой по сравнению с ObjectListView (который я использовал много раз, без каких-либо серьезных проблем). Я потратил некоторое время на поиск более или менее эквивалентной (бесплатной) замены, но, похоже, там ничего нет. Даже с бедами его все еще большой компонент. счастливое кодирование ... –

+0

Спасибо Rev1.0 - Я согласен с лучшими пока, но немного причудами. – Simon

0

«Рекурсивный вызов функции, когда элементы CheckState изменения (и обеспечение последующих событий ItemCheck игнорируется в то время как программно меняется CheckStates)»

В случае TreeListView самоконтроль («из коробки») является хорошо для вас, и вы просто хотите знать, когда весь персонал после вашего руководства будет сделан основной щелчок по кнопке (это означает: вы нажмете, TreeListView (un) проверьте все дочерние и родительские), , поэтому вам нужно сделать дополнительное событие в ObjectListView Библиотека (в грубом порядке):

\ objectlistviewdemo \ objectlistview \ treelistview.CS

Во-первых, добавить событие (мои события плохо, но вы знаете, что исправить)

#region Events 

    public delegate void AfterTreeCheckEventHandler(object sender/*, object rowmodel*/); 

    /// <summary> 
    /// Triggered when clicked main checkbox checked and all related too. 
    /// </summary> 
    [Category("ObjectListView"), 
    Description("This event is triggered when clicked main checkbox checked and all related too.")] 
    public event AfterTreeCheckEventHandler AfterTreeCheckAndRecalculate; 

    #endregion 

    #region OnEvents 

    /// <summary> 
    /// Tell the world when a cell has finished being edited. 
    /// </summary> 
    protected virtual void OnAfterTreeCheckAndRecalculate(/*CellEditEventArgs e*/) 
    { 
     if (this.AfterTreeCheckAndRecalculate != null) 
      this.AfterTreeCheckAndRecalculate(this/*, e*/); 
    } 

    #endregion 

Во-вторых вам нужно исправить «SetObjectCheckedness» метод (1 рекурсивный метод 1 простой + 1 рекурсивной)

 /// <summary> 
    /// Change the check state of the given object to be the given state. 
    /// </summary> 
    /// <remarks> 
    /// If the given model object isn't in the list, we still try to remember 
    /// its state, in case it is referenced in the future.</remarks> 
    /// <param name="modelObject"></param> 
    /// <param name="state"></param> 
    /// <returns>True if the checkedness of the model changed</returns> 
    protected override bool SetObjectCheckedness(object modelObject, CheckState state) { 
     // If the checkedness of the given model changes AND this tree has 
     // hierarchical checkboxes, then we need to update the checkedness of 
     // its children, and recalculate the checkedness of the parent (recursively) 

     bool result = SetObjectCheckednessHelper(modelObject, state, 0); 

     if (this.AfterTreeCheckAndRecalculate != null) 
      this.AfterTreeCheckAndRecalculate(this); //report that work is done 
     return result; 
    } 

    protected bool SetObjectCheckednessHelper(object modelObject, CheckState state, int i) //recursive 
    { 
     if (!base.SetObjectCheckedness(modelObject, state)) 
      return false; 

     if (!this.HierarchicalCheckboxes) 
      return true; 

     // Give each child the same checkedness as the model 

     CheckState? checkedness = this.GetCheckState(modelObject); 
     if (!checkedness.HasValue || checkedness.Value == CheckState.Indeterminate) 
      return true; 

     foreach (object child in this.GetChildrenWithoutExpanding(modelObject)) 
     { 
      this.SetObjectCheckednessHelper(child, checkedness.Value, i+1); 
     } //(un)check all children checkboxes 

     if (i == 0) //recalculate upper levels only in the case of first call 
     { 
      ArrayList args = new ArrayList(); 
      args.Add(modelObject); 
      this.RecalculateHierarchicalCheckBoxGraph(args); //all upper checkboxes in intermediate state or (un)check 
     } 

     return true; 
    } 

использование:

this.olvDataTree.AfterTreeCheckAndRecalculate += new BrightIdeasSoftware.TreeListView.AfterTreeCheckEventHandler(this.olvDataTree_TreeChecked); 

    private void olvDataTree_TreeChecked(object sender) 
    { 
      //some staff here 
    } 
+0

плюс в этом случае вы должны исправить в TreeListView.cs: публичных виртуальных IEnumerable детей { <...> набор { <...> если (checkedness.HasValue && checkedness.Value == CheckState.Checked) //treeListView.SetObjectCheckedness (x, checkness.Value); treeListView.SetObjectCheckednessHelper (x, checkness.Value, 0); }} просто замените то, что прокомментировано –

Смежные вопросы