【问题标题】:Adding child nodes to a TreeViewItem in numerical order按数字顺序将子节点添加到 TreeViewItem
【发布时间】:2013-07-30 04:15:24
【问题描述】:

我有一个带有 TreeView 项目的程序,其中包含数字 headers 的子节点。当adding 子节点到TreeViewItem 时,我想以数字方式添加它们,但我不知道如何在其他节点之间添加节点。

我猜我会调用一个对子节点进行排序的函数,将标头转换为integers,将标头与输入的值进行比较,然后在节点标头大于输入的值时停止.新节点必须在标头大于要添加的新节点的节点之前输入。

这是最好的方法,还是有更好的方法?请演示解决此问题的最简单方法。仅供参考,我的TreeViewItem 在我的主窗口中,并且正在从一个单独的窗口进行处理。

这应该让您了解如何将子节点添加到我的TreeViewItem

//Global boolean    
// bool isDuplicate;

//OKAY - Add TreeViewItems to location & Checks if location value is numerical
private void button2_Click(object sender, RoutedEventArgs e)
{
      //Checks to see if TreeViewItem is a numerical value
      string Str = textBox1.Text.Trim();
      double Num;

      bool isNum = double.TryParse(Str, out Num);

      //If not numerical value, warn user
      if (isNum == false)
          MessageBox.Show("Value must be Numerical");
      else //else, add location
      {
          //close window
          this.Close();

          //Query for Window1
          var mainWindow = Application.Current.Windows
              .Cast<Window1>()
              .FirstOrDefault(window => window is Window1) as Window1;

          //declare TreeViewItem from mainWindow
          TreeViewItem locations = mainWindow.TreeViewItem;

          //Passes to function -- checks for DUPLICATE locations
          CheckForDuplicate(TreeViewItem.Items, textBox1.Text);

          //if Duplicate exists -- warn user
          if (isDuplicate == true)
             MessageBox.Show("Sorry, the number you entered is a duplicate of a current node, please try again.");
          else //else -- create node
          {
               //Creates TreeViewItems for Location
               TreeViewItem newNode = new TreeViewItem();

               //Sets Headers for new locations
               newNode.Header = textBox1.Text;

               //Add TreeView Item to Locations & Blocking Database
               mainWindow.TreeViewItem.Items.Add(newNode);

           }
       }
}

//Checks to see whether the header entered is a DUPLICATE
private void CheckForDuplicate(ItemCollection treeViewItems, string input)
{
      for (int index = 0; index < treeViewItems.Count; index++)
      {
             TreeViewItem item = (TreeViewItem)treeViewItems[index];
             string header = item.Header.ToString();

             if (header == input)
             {
                   isDuplicate = true;
                   break;
             }
             else
                   isDuplicate = false;
      }
}

谢谢。

【问题讨论】:

  • 当您的结构变得更加复杂时,我发现了潜在的问题。您如何处理具有多个孩子的节点?如果这个节点的路径是排序的,它的兄弟节点也会被排序吗?当你移动一个节点时,你是移动它的子节点还是将它们添加到新的父节点?
  • 我现在只和一位家长打交道。此TreeViewItem 的子代只会分配给一个父代。
  • 那么问题将是如何处理子节点的子节点。您需要记住,树形结构意味着一切都是连接的。如果您只使用一条路径保持一切简单,那么您最好将数据放入列表并从列表中的数据填充树视图。如果要对其进行排序,则在每次排序后清除并重新填充树视图。这听起来有些过头了,但是一旦将节点添加到树视图中,它就比删除和插入节点要简单得多。
  • 好的,所以把我的节点放到一个列表中,然后每次更新列表,更新TreeView中的子节点?
  • 是的,但您必须遍历列表并将每一个添加为树视图中最后一个的子级。糟糕,抱歉,没有看到 wpf 标签。 wpf 中可能有更好的方法。

标签: c# wpf treeviewitem


【解决方案1】:

下面是一个使用ModelViewBindingCollectionView 的特殊情况的小示例

模型视图

public class MainViewModel
{
  private readonly ObservableCollection<TreeItemViewModel> internalChildrens;

  public MainViewModel(string topLevelHeader) {
    this.TopLevelHeader = topLevelHeader;
    this.internalChildrens = new ObservableCollection<TreeItemViewModel>();
    var collView = CollectionViewSource.GetDefaultView(this.internalChildrens);
    collView.SortDescriptions.Add(new SortDescription("Header", ListSortDirection.Ascending));
    this.Childrens = collView;
  }

  public string TopLevelHeader { get; set; }

  public IEnumerable Childrens { get; set; }

  public bool AddNewChildren(double num) {
    var numExists = this.internalChildrens.FirstOrDefault(c => c.Header == num) != null;
    if (!numExists) {
      this.internalChildrens.Add(new TreeItemViewModel() {Header = num});
    }
    return numExists;
  }
}

public class TreeItemViewModel
{
  public double Header { get; set; }
}

Xaml

<Window x:Class="WpfStackOverflowSpielWiese.Window21"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window21"
        Height="300"
        Width="300"
        x:Name="tvExample">

  <Grid DataContext="{Binding ElementName=tvExample, Path=ViewModel, Mode=OneWay}">

    <StackPanel Orientation="Vertical">
      <TextBox x:Name="tb" />
      <Button Content="Add"
              Click="AddNewItemOnClick" />
      <TreeView>
        <TreeViewItem Header="{Binding TopLevelHeader, Mode=OneWay}"
                      ItemsSource="{Binding Childrens, Mode=OneWay}">
          <TreeViewItem.ItemTemplate>
            <HierarchicalDataTemplate>
              <TextBlock Text="{Binding Header}" />
            </HierarchicalDataTemplate>
          </TreeViewItem.ItemTemplate>
        </TreeViewItem>
      </TreeView>
    </StackPanel>

  </Grid>

</Window>

Xaml 代码背后

public partial class Window21 : Window
{
  public static readonly DependencyProperty ViewModelProperty =
    DependencyProperty.Register("ViewModel", typeof(MainViewModel), typeof(Window21), new PropertyMetadata(default(MainViewModel)));

  public MainViewModel ViewModel {
    get { return (MainViewModel)this.GetValue(ViewModelProperty); }
    set { this.SetValue(ViewModelProperty, value); }
  }

  public Window21() {
    this.InitializeComponent();
    this.ViewModel = new MainViewModel("TopLevel");
  }

  private void AddNewItemOnClick(object sender, RoutedEventArgs e) {
    double Num;
    var isNum = double.TryParse(this.tb.Text, out Num);
    //If not numerical value, warn user
    if (isNum == false) {
      MessageBox.Show("Value must be Numerical");
      return;
    }

    var isDuplicate = this.ViewModel.AddNewChildren(Num);
    if (isDuplicate) {
      MessageBox.Show("Sorry, the number you entered is a duplicate of a current node, please try again.");
      return;
    }
  }
}

希望对你有帮助

【讨论】:

  • 我把它放到一个测试程序中看看它是如何工作的,我得到的唯一错误是public IEnumerable Childrens { get; set; } 的行。编译器说,Using the generic type 'System.Collections.Generic.IEnumerable&lt;T&gt;' requires '1' type arguments。也许你知道这意味着什么。
  • @Ericafterdark 你需要 System.Collections 而不是 System.Collections.Generic 使用(NET4)
  • 好的,它正在工作。不过,我仍然必须努力将其实施到我的程序中。谢谢。
  • 与@tinstaafl 的方式相比,您认为这是一种更复杂的方式吗?如果我只是将所有节点放入一个列表中会怎样?
猜你喜欢
  • 2017-02-14
  • 1970-01-01
  • 2012-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-31
相关资源
最近更新 更多