2009-12-31 8 views
0

Я новичок в использовании древовидных представлений, и я хочу, чтобы убедиться, что в древовидном представлении проверен только один дочерний узел, и если кто-то пытается проверить более одного, то он останавливает событие проверки и отменяет выбор всех родительских и дочерних узлов. Как мне это сделать? Пока это то, что у меня есть, но это причудливо. Какие-либо предложения?Проверить количество проверенных узлов в TreeView

Обновление: Чтобы прояснить некоторые вещи, это дерево формы win, а родительский узел - это категория, и каждая категория может содержать несколько элементов. Я хочу, чтобы пользователь мог выбирать одну категорию и один элемент из категории за раз.

private void tvRecipes_BeforeCheck(object sender, TreeViewCancelEventArgs e) 
{ 
    int checkedNodeCount = 0; 

    if (e.Node.Parent != null && !e.Node.Parent.Checked) 
     e.Cancel = true; 
    else 
    { 
     foreach (TreeNode node in tvRecipes.Nodes) 
     { 
      if (node.Checked) 
       ++checkedNodeCount; 

      if (checkedNodeCount > 2) 
      { 
       MessageBox.Show("Only one recipe can be selected at a time, please deselect the current recipe and try again.", "Too Many Recipes Selected", MessageBoxButtons.OK, MessageBoxIcon.Error); 

       e.Cancel = true; 
      } 
     } 
    } 

После некоторого беспорядка я выяснил решение, которое я получил после. Я разместил его ниже:

private bool CheckNumOfSelectedChildern(TreeViewEventArgs e) 
{ 
    bool Valid = true; 
    int selectedChildern = 0; 

    foreach (TreeNode node in tvRecipes.Nodes) 
    { 
     if (node.Checked) 
     { 
      foreach (TreeNode child in node.Nodes) 
      { 
       if (child.Checked) 
        ++selectedChildern; 
      } 
     } 
    } 

    if (selectedChildern > 1) 
    { 
     MessageBox.Show("Only one recipe per category can be selected at a time, please deselect the current recipe and try again.", "Too Many Recipes Selected", MessageBoxButtons.OK, MessageBoxIcon.Error); 
     e.Node.Checked = false; 
     e.Node.Parent.Checked = false; 
     Valid = false; 
    }  
    return Valid; 
} 

private bool CheckNumOfSelectedParents(TreeViewEventArgs e) 
{ 
    bool Valid = true; 
    int selectedParent = 0; 

    foreach (TreeNode root in tvRecipes.Nodes) 
    { 
     if (root.Checked) 
      ++selectedParent; 
    } 

    if (selectedParent > 1) 
    { 
     MessageBox.Show("Only one recipe category can be selected at a time, please deselect the current recipe and try again.", "Too Many Recipes Selected", MessageBoxButtons.OK, MessageBoxIcon.Error); 
     e.Node.Checked = false; 
     Valid = false; 
    } 
    return Valid; 
} 

private void tvRecipes_BeforeCheck(object sender, TreeViewCancelEventArgs e) 
{ 
    if (e.Node.Parent != null && !e.Node.Parent.Checked) 
     e.Cancel = true; 
    else if (e.Node.Checked) 
    { 
     foreach (TreeNode child in e.Node.Nodes) 
     { 
      if (child.Checked) 
       e.Cancel = true; 
     } 
    } 
} 

private void tvRecipes_AfterCheck(object sender, TreeViewEventArgs e) 
{ 
    if (CheckNumOfSelectedParents(e)) 
    { 
     if (e.Node.Parent != null && e.Node.Parent.Checked) 
     { 
      if (e.Node.Checked) 
      { 
       if (CheckNumOfSelectedChildern(e)) 
       { 
        RecipeDs = RetrieveRecipe.FillRecipeDs(e.Node.Text); 
        DataBindControls(); 
       }      
      } 
      else 
      { 
       RemoveLabelsFromLayout(); 
       RemoveDataBindings(); 
       RecipeDs.Clear(); 
       this.Refresh(); 
      } 
     } 
    } 
} 
+0

@ Натан, Привет, я вижу, вы приняли мой ответ, это скорее длинный «комментарий», чем конкретный ответ на ваш вопрос. Я не уверен, что мой «длинный комментарий», представляющий «как ответ», заслуживает принятия, поэтому, пожалуйста, если вы получите «лучший ответ», не стесняйтесь его выбирать. Еще раз позвольте (мягко) предложить вам немного уточнить свой вопрос. best, – BillW

+0

@Nathan, несколько вопросов: 1. по дизайну конечный пользователь не может проверить или снять отметки с узлов категории? 2. если пользователь может проверить узел категории (корневой): но не выбирает элемент (дочерний узел) в пределах выбранного узла категории: это условие ошибки? 3. Только действие проверки дочернего узла будет автоматически проверять корневой узел, который является родителем категории дочернего узла, который вы только что отметили? 4. Если мне удастся снять отметку с узла категории, и у меня есть узел элемента в его родительском (классе) узле, отмеченном, когда я снижу отметку элемента ndoe: узел категории (родительский узел) также должен быть отмечен флажком? – BillW

+0

@Nathan, Привет, как только мы точно знаем, что можно и не может быть сделано с узлами категории (без родителя, корневыми узлами), эту ситуацию легко справиться с помощью одного или двух логических флагов или, возможно, только с помощью двух ссылки на текущий узел категории (без родителя, root) и текущий элемент узла (дочерний узел). best, – BillW

ответ

1

Это слишком долго, просто комментарий.

Я предполагаю, что вы описываете стандартный Windows Forms TreeView: правильно?

Когда вы говорите в своем вопросе:

если кто-то пытается проверить более один он останавливает проверку события и пометку со всех родительских и дочерних узлов.

Для меня это означает, что вы есть TreeView способны множественный выбор, и стандартный Windows Forms TreeView является не способна. Вы можете «взломать» его, поэтому он делает многоэкранный выбор: например, CodeProject : "Multiselect Treeview Implementation", но это не так.

Так что я собираюсь предположить, что вы имели в виду «снимите флажок» Родительские и дочерние узлы: но: это сбивает с толку, потому что ваш вопрос, кажется, ясно спросить, как вы можете иметь только одного ребенка TreeNode проверяется один раз: это означает, для меня, что это никогда не будет так, что вам придется «убрать» любые другие дочерние узлы.

Чтение вашего кода, очевидно, что вы планируете проверить, что один родительский узел проверен, но вы специально не исключаете, что может быть проверено более одного «родительского» (корневого) узла.

Итак, предлагает Перефразирование вашего вопроса немного более четко разъяснить:

  1. более одного сироту (корень) узел можно проверить?

  2. Одновременно можно проверить только один родительский (корневой) узел?

  3. для каждого проверяемого узла без родителя (root), один и только один, дочерний узел может быть проверен в любой момент времени?

  4. если дочерние узлы «глубоко вложены»: это имеет для вас какое-либо значение?

Примечание: из-за больших ограничений встроенного элемента управления WinForms TreeView многие из нас приобрели третью.Сторона Элементы управления TreeView:

Я купил Integral UI TreeView from Lidor Systems и был в восторге от этого. Встроенное свойство Lidor TreeView представляет собой коллекцию CheckedNodes, содержащую все проверенные в настоящее время узлы, и у вас есть выбор из трех режимов выбора, в том числе один «MultiExtended», который позволяет иметь очень сложные варианты выбора, включающие дочерние и родительские узлы в любой порядок на любом уровне «гнездования»:

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

С помощью Lidor TreeView вы можете скрыть CheckBox для любого узла в любое время (во время разработки или во время выполнения), а CheckBox поддерживает три состояния: «неопределенный, а также« отмеченный »и« непроверенный ».

предположим другой 3rd. сторонние элементы управления TreeView также предлагают аналогичные функции, но когда я просмотрел и попробовал «пробные версии» большинства основных двух лет назад, для меня Lidor TreeView предлагал большую ценность и не стоил дорогих. Что касается способности богато «стилизовать» TreeNodes, я не видел ничего близкого к возможности Lidor TreeView в «WinForms Universe». Раскрытие информации: я не работаю для Лидора и не имею деловых отношений с ними: я просто счастливый клиент, который рад порекомендовать.

1

Ваш if (checkedNodeCount> 2) ... должен находиться вне цикла foreach.

Внутри цикла for он запускается каждый раз. Я предполагаю, что это то, что вы имеете в виду под «притворством»

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

1

Надеется, что это работает:

private int _callCountUp; 

     private int _callCountDn; 

private void tvwPermissions_AfterCheck(object sender, System.Windows.Forms.TreeViewEventArgs e) 
     { 
      bool anyChecked = false; 

      if (_callCountDn == 0 && e.Node.Parent != null) 
      { 
       anyChecked = false; 
       foreach (TreeNode childNode in e.Node.Parent.Nodes) 
       { 
        if (childNode.Checked) 
        { 
         anyChecked = true; 
         break; 
        } 
       } 
       _callCountUp += 1; 

       if (anyChecked) 
        e.Node.Parent.Checked = true; 

       _callCountUp -= 1; 
      } 

      if (_callCountUp == 0) 
      { 
       foreach (TreeNode childNode in e.Node.Nodes) 
       { 
        _callCountDn += 1; 
        childNode.Checked = e.Node.Checked; 
        _callCountDn -= 1; 
       } 
      } 
     } 
0

Это было предложено 1 год назад, но there это подсказка, как выбрать только один узел в Treeview

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