Przeglądaj źródła

新建树,删除树

tanghai 11 lat temu
rodzic
commit
9701c5483c

+ 11 - 5
CSharp/App/Modules/Tree/AllTreeView.xaml

@@ -13,7 +13,6 @@
 		<MenuItem Header="File">
 			<MenuItem Header="打开" Click="MenuItem_Open" />
 			<MenuItem Header="保存" Click="MenuItem_Save" />
-			<MenuItem Header="新建" Click="MenuItem_New" />
 		</MenuItem>
 	</Menu>
 	<Grid>
@@ -27,11 +26,18 @@
 			<ColumnDefinition />
 		</Grid.ColumnDefinitions>
 		<GroupBox Grid.Row="0" Grid.Column="0" Header="行为树列表:">
-			<ListBox Name="lbTreeId" ItemsSource="{Binding TreeList}" VerticalAlignment="Stretch" >
+			<ListBox Name="lbTreeRoots" ItemsSource="{Binding RootList}" VerticalAlignment="Stretch" >
+				<ListBox.ContextMenu>
+					<ContextMenu>
+						<MenuItem Header="新建树" Click="MenuItem_New" />
+						<MenuItem Header="删除树" Click="MenuItem_Remove" />
+					</ContextMenu>
+				</ListBox.ContextMenu>
 				<ListBox.ItemTemplate>
-					<DataTemplate DataType="Tree:TreeInfoViewModel">
-						<StackPanel MouseLeftButtonDown="OnMouseLeftButtonDown" Orientation="Horizontal" Margin="1,0">
-							<Label Content="{Binding Id}" VerticalAlignment="Stretch" Width="20" ></Label>
+					<DataTemplate DataType="Tree:TreeNodeViewModel">
+						<StackPanel MouseLeftButtonDown="ListBoxItem_OnMouseLeftButtonDown" MouseLeftButtonUp="ListBoxItem_OnMouseLeftButtonUp" 
+									Orientation="Horizontal" Margin="1,0">
+							<Label Content="{Binding TreeId}" VerticalAlignment="Stretch" Width="20" ></Label>
 							<Label Content="{Binding Comment}" VerticalAlignment="Stretch" Width="150"></Label>
 						</StackPanel>
 					</DataTemplate>

+ 33 - 6
CSharp/App/Modules/Tree/AllTreeView.xaml.cs

@@ -37,28 +37,55 @@ namespace Modules.Tree
 
         private void MenuItem_Open(object sender, RoutedEventArgs e)
         {
+            this.ViewModel.Open("node.bytes");
+            this.lbTreeRoots.SelectedIndex = -1;
+            this.treeView.ViewModel = null;
         }
 
         private void MenuItem_Save(object sender, RoutedEventArgs e)
         {
+            this.ViewModel.Save("node.bytes");
         }
 
         private void MenuItem_New(object sender, RoutedEventArgs e)
         {
-            TreeViewModel treeViewModel = new TreeViewModel(new List<TreeNodeData>());
+            TreeViewModel treeViewModel = new TreeViewModel(this.ViewModel);
             this.ViewModel.Add(treeViewModel);
             this.treeView.ViewModel = treeViewModel;
         }
 
-        private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+        private void MenuItem_Remove(object sender, RoutedEventArgs e)
         {
-            var item = (FrameworkElement)sender;
-            var treeInfoViewModel = item.DataContext as TreeInfoViewModel;
-            if (this.treeView.ViewModel.TreeId == treeInfoViewModel.Id)
+            if (this.lbTreeRoots.SelectedItem == null)
             {
                 return;
             }
-            this.treeView.ViewModel = this.ViewModel.Get(treeInfoViewModel.Id);
+            var treeNodeViewModel = this.lbTreeRoots.SelectedItem as TreeNodeViewModel;
+            this.ViewModel.Remove(treeNodeViewModel);
+            this.lbTreeRoots.SelectedItem = null;
+            e.Handled = true;
+        }
+
+        private void ListBoxItem_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+        {
+            var item = (FrameworkElement)sender;
+            var treeNodeViewModel = item.DataContext as TreeNodeViewModel;
+            if (this.treeView.ViewModel != null)
+            {
+                if (this.treeView.ViewModel.TreeId == treeNodeViewModel.TreeId)
+                {
+                    return;
+                }
+            }
+            this.treeView.ViewModel = this.ViewModel.Get(treeNodeViewModel.TreeId);
+        }
+
+        private void ListBoxItem_OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
+        {
+            var item = (FrameworkElement)sender;
+            var treeNodeViewModel = item.DataContext as TreeNodeViewModel;
+
+            this.lbTreeRoots.SelectedItem = treeNodeViewModel;
         }
     }
 }

+ 46 - 27
CSharp/App/Modules/Tree/AllTreeViewModel.cs

@@ -10,42 +10,41 @@ namespace Modules.Tree
      PartCreationPolicy(creationPolicy: CreationPolicy.NonShared)]
     public class AllTreeViewModel
     {
-        private AllTreeData allTreeData;
-
         public int MaxNodeId { get; set; }
         public int MaxTreeId { get; set; }
+        
+        private readonly Dictionary<int, TreeViewModel> treeViewModelsDict = new Dictionary<int, TreeViewModel>();
 
-        public Dictionary<int, List<TreeNodeData>> treeDict = new Dictionary<int, List<TreeNodeData>>();
-
-        private readonly Dictionary<int, TreeViewModel> treeViewModelsDict = new Dictionary<int, TreeViewModel>(); 
-
-        public ObservableCollection<TreeInfoViewModel> treeList = new ObservableCollection<TreeInfoViewModel>();
+        public ObservableCollection<TreeNodeViewModel> rootList = new ObservableCollection<TreeNodeViewModel>();
 
-        public ObservableCollection<TreeInfoViewModel> TreeList
+        public ObservableCollection<TreeNodeViewModel> RootList
         {
             get
             {
-                return this.treeList;
+                return this.rootList;
             }
         }
 
-        public void Load(string file)
+        public void Open(string file)
         {
-            treeDict.Clear();
-            treeList.Clear();
+            this.rootList.Clear();
+            treeViewModelsDict.Clear();
+
+            var treeDict = new Dictionary<int, List<TreeNodeData>>();
+
             byte[] bytes = File.ReadAllBytes(file);
-            this.allTreeData = ProtobufHelper.FromBytes<AllTreeData>(bytes);
+            var allTreeData = ProtobufHelper.FromBytes<AllTreeData>(bytes);
 
             this.MaxNodeId = 0;
             this.MaxTreeId = 0;
             foreach (TreeNodeData treeNodeData in allTreeData.TreeNodeDatas)
             {
                 List<TreeNodeData> tree;
-                this.treeDict.TryGetValue(treeNodeData.TreeId, out tree);
+                treeDict.TryGetValue(treeNodeData.TreeId, out tree);
                 if (tree == null)
                 {
                     tree = new List<TreeNodeData>();
-                    this.treeDict[treeNodeData.TreeId] = tree;
+                    treeDict[treeNodeData.TreeId] = tree;
                 }
                 tree.Add(treeNodeData);
                 if (treeNodeData.Id > this.MaxNodeId)
@@ -56,13 +55,35 @@ namespace Modules.Tree
                 {
                     this.MaxTreeId = treeNodeData.TreeId;
                 }
+            }
 
-                treeList.Add(new TreeInfoViewModel(treeNodeData.TreeId, treeNodeData.TreeId.ToString()));
+            foreach (KeyValuePair<int, List<TreeNodeData>> pair in treeDict)
+            {
+                var treeViewModel = new TreeViewModel(pair.Value)
+                {
+                    AllTreeViewModel = this,
+                    TreeId = pair.Key
+                };
+                treeViewModelsDict[pair.Key] = treeViewModel;
+                this.RootList.Add(treeViewModel.Root);
             }
         }
 
         public void Save(string file)
         {
+
+            AllTreeData allTreeData = new AllTreeData();
+            foreach (var value in treeViewModelsDict.Values)
+            {
+                List<TreeNodeData> list = value.GetDatas();
+                allTreeData.TreeNodeDatas.AddRange(list);
+            }
+
+            using (Stream stream = new FileStream(file, FileMode.Create, FileAccess.Write))
+            {
+                byte[] bytes = ProtobufHelper.ToBytes(allTreeData);
+                stream.Write(bytes, 0, bytes.Length);
+            }
         }
 
         public void New(TreeViewModel treeViewModel)
@@ -71,22 +92,20 @@ namespace Modules.Tree
 
         public void Add(TreeViewModel treeViewModel)
         {
-            treeViewModel.TreeId = ++this.MaxTreeId;
-            treeViewModel.AllTreeViewModel = this;
-            treeDict[treeViewModel.TreeId] = treeViewModel.TreeNodeDatas;
             treeViewModelsDict[treeViewModel.TreeId] = treeViewModel;
-            this.treeList.Add(new TreeInfoViewModel(treeViewModel.TreeId, treeViewModel.TreeId.ToString()));
+            this.rootList.Add(treeViewModel.Root);
+        }
+
+        public void Remove(TreeNodeViewModel treeViewModel)
+        {
+            treeViewModelsDict.Remove(treeViewModel.TreeId);
+            rootList.Remove(treeViewModel);
         }
 
         public TreeViewModel Get(int treeId)
         {
-            if (this.treeViewModelsDict.ContainsKey(treeId))
-            {
-                return this.treeViewModelsDict[treeId];
-            }
-            var treeViewModel = new TreeViewModel(this.treeDict[treeId]);
-            this.treeViewModelsDict[treeId] = treeViewModel;
-            return treeViewModel;
+            return this.treeViewModelsDict[treeId];
         }
+
     }
 }

+ 16 - 12
CSharp/App/Modules/Tree/NodeDataEditor.xaml

@@ -9,27 +9,31 @@
 	<UserControl.Resources>
 		<tree:ListToStringConverter x:Key="ListToStringConverter"/>
 	</UserControl.Resources>
-	
+
 	<Grid VerticalAlignment="Stretch">
 		<Grid.RowDefinitions>
 			<RowDefinition Height="*"/>
 			<RowDefinition Height="*"/>
 			<RowDefinition Height="*"/>
+			<RowDefinition Height="*"/>
 			<RowDefinition Height="4*"/>
 			<RowDefinition Height="*"/>
 		</Grid.RowDefinitions>
 		<Grid.ColumnDefinitions>
-			<ColumnDefinition Width="47*"/>
-			<ColumnDefinition Width="154*"/>
+			<ColumnDefinition Width="40*"/>
+			<ColumnDefinition Width="171*"/>
 		</Grid.ColumnDefinitions>
-		<Label Content="ID: " Grid.Row="0" Grid.Column="0" HorizontalAlignment="Center" HorizontalContentAlignment="Center" VerticalAlignment="Top" VerticalContentAlignment="Stretch" Height="26" Margin="0,0,19,0" Width="28" />
-		<Label Content="类型:" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Center" HorizontalContentAlignment="Center" VerticalAlignment="Top" Height="26" Margin="-2,0,9,0" Width="40" />
-		<Label Content="参数:" Grid.Row="2" Grid.Column="0" HorizontalAlignment="Center" HorizontalContentAlignment="Center" VerticalAlignment="Top" Height="26" Margin="-2,1,9,0" Width="40" />
-		<Label Content="备注:" Grid.Row="3" Grid.Column="0" HorizontalAlignment="Center" HorizontalContentAlignment="Center" VerticalAlignment="Top" Height="26" Margin="0,40,9,0" Width="40" />
-		<Label Name="lblId" Grid.Column="1" Grid.Row="0" Margin="2" Content="{Binding Id}" />
-		<ComboBox Name="cbType" Grid.Column="1" Grid.Row="1" Margin="2" SelectionChanged="CbType_OnSelectionChanged" />
-		<TextBox Name="tbArgs" Grid.Column="1" Grid.Row="2" Margin="2" Text="{Binding Args, Converter={StaticResource ListToStringConverter}}" />
-		<TextBox Name="tbComment" Grid.Column="1" Grid.Row="3" Margin="2" Text="{Binding Comment}" />
-		<Button Content="OK" Grid.Row="4" Grid.Column="1" Margin="1,1,40,1"/>
+		<Label Content="Tree:" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Left" HorizontalContentAlignment="Center" VerticalAlignment="Top" VerticalContentAlignment="Stretch" Height="30" />
+		<Label Content="ID  :" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Left" HorizontalContentAlignment="Center" VerticalAlignment="Top" VerticalContentAlignment="Stretch" Height="30"/>
+		<Label Content="类型:" Grid.Row="2" Grid.Column="0" HorizontalAlignment="Left" HorizontalContentAlignment="Center" VerticalAlignment="Top" Height="30"/>
+		<Label Content="参数:" Grid.Row="3" Grid.Column="0" HorizontalAlignment="Left" HorizontalContentAlignment="Center" VerticalAlignment="Top" Height="30"/>
+		<Label Content="备注:" Grid.Row="4" Grid.Column="0" HorizontalAlignment="Left" HorizontalContentAlignment="Center" VerticalAlignment="Top" Height="30"/>
+		
+		<Label Name="lblTreeId" Grid.Column="1" Grid.Row="0" Content="{Binding TreeId}" />
+		<Label Name="lblId" Grid.Column="1" Grid.Row="1" Content="{Binding Id}" />
+		<ComboBox Name="cbType" Grid.Column="1" Grid.Row="2" Margin="2" SelectionChanged="CbType_OnSelectionChanged" />
+		<TextBox Name="tbArgs" Grid.Column="1" Grid.Row="3" Margin="2" Text="{Binding Args, Converter={StaticResource ListToStringConverter}}" />
+		<TextBox Name="tbComment" Grid.Column="1" Grid.Row="4" Margin="2" Text="{Binding Comment}" />
+		<Button Content="OK" Grid.Row="5" Grid.Column="1" Width="100" HorizontalAlignment="Left"/>
 	</Grid>
 </UserControl>

+ 35 - 35
CSharp/App/Modules/Tree/TreeLayout.cs

@@ -16,16 +16,16 @@
         }
 
         private TreeNodeViewModel LeftMostOffspring(
-                TreeNodeViewModel treeNode, int currentLevel, int searchLevel)
+                TreeNodeViewModel treeNodeViewModel, int currentLevel, int searchLevel)
         {
             if (currentLevel == searchLevel)
             {
-                return treeNode;
+                return treeNodeViewModel;
             }
-            for (int i = 0; i < treeNode.Children.Count; ++i)
+            for (int i = 0; i < treeNodeViewModel.Children.Count; ++i)
             {
-                var child = this.treeViewModel.Get(treeNode.Children[i]);
-                child.AncestorModify = treeNode.Modify + treeNode.AncestorModify;
+                var child = this.treeViewModel.Get(treeNodeViewModel.Children[i]);
+                child.AncestorModify = treeNodeViewModel.Modify + treeNodeViewModel.AncestorModify;
                 var offspring = LeftMostOffspring(child, currentLevel + 1, searchLevel);
                 if (offspring == null)
                 {
@@ -37,16 +37,16 @@
         }
 
         private TreeNodeViewModel RightMostOffspring(
-                TreeNodeViewModel treeNode, int currentLevel, int searchLevel)
+                TreeNodeViewModel treeNodeViewModel, int currentLevel, int searchLevel)
         {
             if (currentLevel == searchLevel)
             {
-                return treeNode;
+                return treeNodeViewModel;
             }
-            for (int i = treeNode.Children.Count - 1; i >= 0; --i)
+            for (int i = treeNodeViewModel.Children.Count - 1; i >= 0; --i)
             {
-                var child = this.treeViewModel.Get(treeNode.Children[i]);
-                child.AncestorModify = treeNode.Modify + treeNode.AncestorModify;
+                var child = this.treeViewModel.Get(treeNodeViewModel.Children[i]);
+                child.AncestorModify = treeNodeViewModel.Modify + treeNodeViewModel.AncestorModify;
                 var offspring = RightMostOffspring(child, currentLevel + 1, searchLevel);
                 if (offspring == null)
                 {
@@ -79,22 +79,22 @@
             right.Prelim += offset;
         }
 
-        private void AjustTreeGap(TreeNodeViewModel treeNode)
+        private void AjustTreeGap(TreeNodeViewModel treeNodeViewModel)
         {
-            for (int i = 0; i < treeNode.Children.Count - 1; ++i)
+            for (int i = 0; i < treeNodeViewModel.Children.Count - 1; ++i)
             {
-                for (int j = i + 1; j < treeNode.Children.Count; ++j)
+                for (int j = i + 1; j < treeNodeViewModel.Children.Count; ++j)
                 {
-                    var left = this.treeViewModel.Get(treeNode.Children[i]);
-                    var right = this.treeViewModel.Get(treeNode.Children[j]);
+                    var left = this.treeViewModel.Get(treeNodeViewModel.Children[i]);
+                    var right = this.treeViewModel.Get(treeNodeViewModel.Children[j]);
                     AjustSubTreeGap(left, right);
                 }
             }
         }
 
-        private void CalculatePrelimAndModify(TreeNodeViewModel treeNode)
+        private void CalculatePrelimAndModify(TreeNodeViewModel treeNodeViewModel)
         {
-            foreach (int childId in treeNode.Children)
+            foreach (int childId in treeNodeViewModel.Children)
             {
                 TreeNodeViewModel child = this.treeViewModel.Get(childId);
                 CalculatePrelimAndModify(child);
@@ -103,58 +103,58 @@
             double prelim = 0;
             double modify = 0;
 
-            if (treeNode.IsLeaf)
+            if (treeNodeViewModel.IsLeaf)
             {
-                if (treeNode.LeftSibling == null)
+                if (treeNodeViewModel.LeftSibling == null)
                 {
                     // 如果没有左邻居,不需要设置modify
                     prelim = 0;
                 }
                 else
                 {
-                    prelim = treeNode.LeftSibling.Prelim + TreeNodeViewModel.Width + XGap;
+                    prelim = treeNodeViewModel.LeftSibling.Prelim + TreeNodeViewModel.Width + XGap;
                 }
             }
             else
             {
                 // 调整子树间的间距
-                AjustTreeGap(treeNode);
-                double childrenCenter = (treeNode.FirstChild.Prelim + treeNode.LastChild.Prelim) / 2;
-                if (treeNode.LeftSibling == null)
+                AjustTreeGap(treeNodeViewModel);
+                double childrenCenter = (treeNodeViewModel.FirstChild.Prelim + treeNodeViewModel.LastChild.Prelim) / 2;
+                if (treeNodeViewModel.LeftSibling == null)
                 {
                     // 如果没有左邻居,不需要设置modify
                     prelim = childrenCenter;
                 }
                 else
                 {
-                    prelim = treeNode.LeftSibling.Prelim + TreeNodeViewModel.Width + XGap;
+                    prelim = treeNodeViewModel.LeftSibling.Prelim + TreeNodeViewModel.Width + XGap;
                     modify = prelim - childrenCenter;
                 }
             }
-            treeNode.Prelim = prelim;
-            treeNode.Modify = modify;
+            treeNodeViewModel.Prelim = prelim;
+            treeNodeViewModel.Modify = modify;
 
-            // Log.Debug("Id: " + treeNode.Id + " Prelim: " + treeNode.Prelim + " Modify: " +
-            // 	treeNode.Modify);
+            // Log.Debug("Id: " + treeNodeViewModel.Id + " Prelim: " + treeNodeViewModel.Prelim + " Modify: " +
+            // 	treeNodeViewModel.Modify);
         }
 
         private void CalculateRelativeXAndY(
-                TreeNodeViewModel treeNode, int level, double totalModify)
+                TreeNodeViewModel treeNodeViewModel, int level, double totalModify)
         {
-            foreach (int childId in treeNode.Children)
+            foreach (int childId in treeNodeViewModel.Children)
             {
                 TreeNodeViewModel child = this.treeViewModel.Get(childId);
-                CalculateRelativeXAndY(child, level + 1, treeNode.Modify + totalModify);
+                CalculateRelativeXAndY(child, level + 1, treeNodeViewModel.Modify + totalModify);
             }
-            if (treeNode.IsLeaf)
+            if (treeNodeViewModel.IsLeaf)
             {
-                treeNode.X = treeNode.Prelim + totalModify;
+                treeNodeViewModel.X = treeNodeViewModel.Prelim + totalModify;
             }
             else
             {
-                treeNode.X = (treeNode.FirstChild.X + treeNode.LastChild.X) / 2;
+                treeNodeViewModel.X = (treeNodeViewModel.FirstChild.X + treeNodeViewModel.LastChild.X) / 2;
             }
-            treeNode.Y = level * (TreeNodeViewModel.Height + YGap);
+            treeNodeViewModel.Y = level * (TreeNodeViewModel.Height + YGap);
         }
 
         private void FixXAndY(TreeNodeViewModel treeNode)

+ 46 - 38
CSharp/App/Modules/Tree/TreeNodeViewModel.cs

@@ -9,7 +9,7 @@ namespace Modules.Tree
         private static double width = 80;
         private static double height = 50;
         private readonly TreeViewModel treeViewModel;
-        private readonly TreeNodeData treeNodeData;
+        private readonly TreeNodeData data;
         private double x;
         private double y;
         private double connectorX2;
@@ -17,16 +17,17 @@ namespace Modules.Tree
         private double prelim;
         private double modify;
         private double ancestorModify;
-        private bool isFolder;
+        private bool isFold;
 
         public TreeNodeViewModel(TreeViewModel treeViewModel, double x, double y)
         {
             this.treeViewModel = treeViewModel;
             this.x = x;
             this.y = y;
-            this.treeNodeData = new TreeNodeData();
-            this.treeNodeData.Id = ++treeViewModel.AllTreeViewModel.MaxNodeId;
-            this.treeNodeData.Parent = 0;
+            this.data = new TreeNodeData();
+            this.data.Id = ++treeViewModel.AllTreeViewModel.MaxNodeId;
+            this.data.TreeId = treeViewModel.TreeId;
+            this.data.Parent = 0;
             this.connectorX2 = 0;
             this.connectorY2 = Height / 2;
         }
@@ -34,8 +35,9 @@ namespace Modules.Tree
         public TreeNodeViewModel(TreeViewModel treeViewModel, TreeNodeViewModel parent)
         {
             this.treeViewModel = treeViewModel;
-            this.treeNodeData = new TreeNodeData();
-            this.treeNodeData.Id = ++treeViewModel.AllTreeViewModel.MaxNodeId;
+            this.data = new TreeNodeData();
+            this.data.Id = ++treeViewModel.AllTreeViewModel.MaxNodeId;
+            this.data.TreeId = treeViewModel.TreeId;
             this.Parent = parent;
 
             this.connectorX2 = Width + this.Parent.X - this.X;
@@ -45,11 +47,11 @@ namespace Modules.Tree
         public TreeNodeViewModel(TreeViewModel treeViewModel, TreeNodeData data)
         {
             this.treeViewModel = treeViewModel;
-            this.treeNodeData = data;
+            this.data = data;
             if (this.IsRoot)
             {
-                this.x = 200;
-                this.y = 10;
+                this.x = 300;
+                this.y = 100;
                 this.connectorX2 = 0;
                 this.connectorY2 = Height / 2;
             }
@@ -60,17 +62,11 @@ namespace Modules.Tree
             }
         }
 
-        public TreeNodeData TreeNodeData
+        public TreeNodeData Data
         {
             get
             {
-                this.treeNodeData.Children.Clear();
-                foreach (int child in this.Children)
-                {
-                    this.treeNodeData.Children.Add(child);
-                }
-                this.treeNodeData.Parent = this.IsRoot? 0 : this.Parent.Id;
-                return this.treeNodeData;
+                return this.data;
             }
         }
 
@@ -78,11 +74,11 @@ namespace Modules.Tree
         {
             get
             {
-                return this.treeNodeData.Id;
+                return this.data.Id;
             }
             set
             {
-                this.treeNodeData.Id = value;
+                this.data.Id = value;
                 this.OnPropertyChanged("Id");
             }
         }
@@ -91,11 +87,11 @@ namespace Modules.Tree
         {
             get
             {
-                return this.treeNodeData.Comment;
+                return this.data.Comment;
             }
             set
             {
-                this.treeNodeData.Comment = value;
+                this.data.Comment = value;
                 this.OnPropertyChanged("Comment");
             }
         }
@@ -257,15 +253,15 @@ namespace Modules.Tree
         {
             get
             {
-                return this.treeNodeData.Type;
+                return this.data.Type;
             }
             set
             {
-                if (this.treeNodeData.Type == value)
+                if (this.data.Type == value)
                 {
                     return;
                 }
-                this.treeNodeData.Type = value;
+                this.data.Type = value;
                 this.OnPropertyChanged("Type");
             }
         }
@@ -274,57 +270,65 @@ namespace Modules.Tree
         {
             get
             {
-                return this.treeNodeData.Args;
+                return this.data.Args;
             }
             set
             {
-                if (this.treeNodeData.Args == value)
+                if (this.data.Args == value)
                 {
                     return;
                 }
-                this.treeNodeData.Args = value;
+                this.data.Args = value;
                 this.OnPropertyChanged("Args");
             }
         }
 
+        public int TreeId
+        {
+            get
+            {
+                return this.data.TreeId;
+            }
+        }
+
         public TreeNodeViewModel Parent
         {
             get
             {
-                if (this.treeNodeData.Parent == 0)
+                if (this.data.Parent == 0)
                 {
                     return null;
                 }
-                TreeNodeViewModel parent = this.treeViewModel.Get(this.treeNodeData.Parent);
+                TreeNodeViewModel parent = this.treeViewModel.Get(this.data.Parent);
                 return parent;
             }
             set
             {
                 if (value == null)
                 {
-                    this.treeNodeData.Parent = 0;
+                    this.data.Parent = 0;
                 }
-                this.treeNodeData.Parent = value.Id;
+                this.data.Parent = value.Id;
             }
         }
 
         /// <summary>
         /// 节点是否折叠
         /// </summary>
-        public bool IsFolder
+        public bool IsFold
         {
             get
             {
-                return this.isFolder;
+                return this.isFold;
             }
             set
             {
-                if (this.isFolder == value)
+                if (this.isFold == value)
                 {
                     return;
                 }
-                this.isFolder = value;
-                this.OnPropertyChanged("IsFolder");
+                this.isFold = value;
+                this.OnPropertyChanged("IsFold");
             }
         }
 
@@ -332,7 +336,11 @@ namespace Modules.Tree
         {
             get
             {
-                return this.treeNodeData.Children;
+                if (this.isFold)
+                {
+                    return new List<int>();
+                }
+                return this.data.Children;
             }
         }
 

+ 3 - 2
CSharp/App/Modules/Tree/TreeView.xaml

@@ -40,7 +40,8 @@
 			<ListBox.ContextMenu>
 				<ContextMenu>
 					<MenuItem Header="新建" Click="MenuItem_New" />
-					<MenuItem Header="删除" Click="MenuItem_Delete" />
+					<MenuItem Header="删除" Click="MenuItem_Remove" />
+					<MenuItem Header="折叠/展开" Click="MenuItem_Fold" />
 				</ContextMenu>
 			</ListBox.ContextMenu>
 			<ListBox.Resources>
@@ -62,7 +63,7 @@
 						<Rectangle Name="rectNode" Width="{Binding Width}" Height="{Binding Height}" Cursor="Hand" StrokeThickness="2"
 								RadiusX="10" RadiusY="10" Stroke="{StaticResource treeNodeBorderBrush}" Fill="{StaticResource treeNodeSelectorFillBrush}">
 						</Rectangle>
-						<Label Content="+" Visibility="{Binding IsFolder, Converter={StaticResource FolderVisiableConverter}}" Canvas.Left="60" Canvas.Top="10"/>
+						<Label Content="+" Visibility="{Binding IsFold, Converter={StaticResource FolderVisiableConverter}}" Canvas.Left="60" Canvas.Top="10"/>
 						<StackPanel>
 							<Label Content="{Binding Type, Converter={StaticResource NodeTypeToStringConverter}}"/>
 							<Label Content="{Binding Comment}"/>

+ 40 - 28
CSharp/App/Modules/Tree/TreeView.xaml.cs

@@ -5,9 +5,6 @@ using Common.Logger;
 
 namespace Modules.Tree
 {
-    /// <summary>
-    /// TreeView.xaml 的交互逻辑
-    /// </summary>
     public partial class TreeView
     {
         private const double DragThreshold = 5;
@@ -35,48 +32,41 @@ namespace Modules.Tree
             }
         }
 
-        private void ListBoxItem_MouseDown(object sender, MouseButtonEventArgs e)
+        public bool IsDragging
         {
-            if (e.ChangedButton != MouseButton.Left)
+            get
             {
-                return;
+                return this.isDragging;
             }
-
-            // 双击鼠标
-            if (e.ClickCount == 2 && e.ChangedButton == MouseButton.Left)
+            set
             {
-                var item = (FrameworkElement)sender;
-                var treeNodeViewModel = item.DataContext as TreeNodeViewModel;
-                if (treeNodeViewModel.IsFolder)
-                {
-                    this.ViewModel.UnFold(treeNodeViewModel);
-                }
-                else
-                {
-                    this.ViewModel.Fold(treeNodeViewModel);
-                }
+                //Mouse.SetCursor(value == false? Cursors.Arrow : Cursors.Hand);
+                this.isDragging = value;
             }
-            e.Handled = true;
+        }
+
+        private void ListBoxItem_MouseDown(object sender, MouseButtonEventArgs e)
+        {
         }
 
         private void ListBoxItem_MouseUp(object sender, MouseButtonEventArgs e)
         {
             if (!this.isLeftButtonDown)
             {
-                this.isDragging = false;
+                this.IsDragging = false;
                 return;
             }
 
             var item = (FrameworkElement)sender;
             var treeNodeViewModel = item.DataContext as TreeNodeViewModel;
 
-            if (!this.isDragging)
+            if (!this.IsDragging)
             {
                 this.listBox.SelectedItem = treeNodeViewModel;
             }
 
             this.isLeftButtonDown = false;
-            this.isDragging = false;
+            this.IsDragging = false;
 
             item.ReleaseMouseCapture();
             e.Handled = true;
@@ -94,7 +84,7 @@ namespace Modules.Tree
             Point curMouseDownPoint;
             Vector dragDelta;
             // 拖动根节点,移动整个树
-            if (this.isDragging && treeNodeViewModel.IsRoot)
+            if (this.IsDragging && treeNodeViewModel.IsRoot)
             {
                 if (this.moveFromNode == null || !this.moveFromNode.IsRoot)
                 {
@@ -111,7 +101,7 @@ namespace Modules.Tree
 
             if (e.LeftButton != MouseButtonState.Pressed)
             {
-                this.isDragging = false;
+                this.IsDragging = false;
                 this.moveFromNode = null;
                 return;
             }
@@ -121,7 +111,7 @@ namespace Modules.Tree
             double dragDistance = Math.Abs(dragDelta.Length);
             if (dragDistance > DragThreshold)
             {
-                this.isDragging = true;
+                this.IsDragging = true;
             }
             e.Handled = true;
         }
@@ -184,7 +174,7 @@ namespace Modules.Tree
                     var parentNode = this.listBox.SelectedItem as TreeNodeViewModel;
                     var addTreeNode = new TreeNodeViewModel(this.ViewModel, parentNode)
                     {
-                        Type = (int)NodeType.Selector
+                        Type = (int)NodeType.Selector,
                     };
                     this.ViewModel.Add(addTreeNode, parentNode);
                 }
@@ -193,16 +183,38 @@ namespace Modules.Tree
             e.Handled = true;
         }
 
-        private void MenuItem_Delete(object sender, RoutedEventArgs e)
+        private void MenuItem_Remove(object sender, RoutedEventArgs e)
         {
             if (this.listBox.SelectedItem == null)
             {
                 return;
             }
             var treeNodeViewModel = this.listBox.SelectedItem as TreeNodeViewModel;
+            if (treeNodeViewModel.IsRoot)
+            {
+                return;
+            }
             this.ViewModel.Remove(treeNodeViewModel);
             this.listBox.SelectedItem = null;
             e.Handled = true;
         }
+
+        private void MenuItem_Fold(object sender, RoutedEventArgs e)
+        {
+            if (this.listBox.SelectedItem == null)
+            {
+                return;
+            }
+            var treeNodeViewModel = this.listBox.SelectedItem as TreeNodeViewModel;
+
+            if (treeNodeViewModel.IsFold)
+            {
+                this.ViewModel.UnFold(treeNodeViewModel);
+            }
+            else
+            {
+                this.ViewModel.Fold(treeNodeViewModel);
+            }
+        }
     }
 }

+ 66 - 45
CSharp/App/Modules/Tree/TreeViewModel.cs

@@ -8,8 +8,6 @@ namespace Modules.Tree
     [Export(typeof (TreeViewModel)), PartCreationPolicy(CreationPolicy.NonShared)]
     public class TreeViewModel: BindableBase
     {
-        private readonly List<TreeNodeData> treeNodeDatas = new List<TreeNodeData>();
-
         private readonly ObservableCollection<TreeNodeViewModel> treeNodes =
                 new ObservableCollection<TreeNodeViewModel>();
 
@@ -25,6 +23,18 @@ namespace Modules.Tree
 
         public int TreeId { get; set; }
 
+        public TreeViewModel(AllTreeViewModel allTreeViewModel)
+        {
+            this.AllTreeViewModel = allTreeViewModel;
+            this.TreeId = ++allTreeViewModel.MaxTreeId;
+            TreeNodeViewModel treeNodeViewModel = new TreeNodeViewModel(this, 300, 100);
+            this.treeNodes.Add(treeNodeViewModel);
+            this.treeNodeDict[treeNodeViewModel.Id] = treeNodeViewModel;
+
+            var treeLayout = new TreeLayout(this);
+            treeLayout.ExcuteLayout(this.Root);
+        }
+
         public TreeViewModel(List<TreeNodeData> treeNodeDatas)
         {
             foreach (TreeNodeData treeNodeData in treeNodeDatas)
@@ -33,19 +43,23 @@ namespace Modules.Tree
                 this.treeNodes.Add(treeNodeViewModel);
                 this.treeNodeDict[treeNodeViewModel.Id] = treeNodeViewModel;
             }
+            var treeLayout = new TreeLayout(this);
+            treeLayout.ExcuteLayout(this.Root);
         }
 
-        public List<TreeNodeData> TreeNodeDatas
+        public List<TreeNodeData> GetDatas()
         {
-            get
+            List<TreeNodeData> treeNodeDatas = new List<TreeNodeData>();
+            foreach (TreeNodeViewModel treeNodeViewModel in treeNodes)
             {
-                return this.treeNodeDatas;
+                treeNodeDatas.Add(treeNodeViewModel.Data);
             }
+            return treeNodeDatas;
         }
 
         public AllTreeViewModel AllTreeViewModel { get; set; }
 
-        private TreeNodeViewModel Root
+        public TreeNodeViewModel Root
         {
             get
             {
@@ -63,7 +77,7 @@ namespace Modules.Tree
         public void Add(TreeNodeViewModel treeNode, TreeNodeViewModel parent)
         {
             // 如果父节点是折叠的,需要先展开父节点
-            if (parent != null && parent.IsFolder)
+            if (parent != null && parent.IsFold)
             {
                 this.UnFold(parent);
             }
@@ -80,24 +94,40 @@ namespace Modules.Tree
             treeLayout.ExcuteLayout(this.Root);
         }
 
-        private void RecursionRemove(TreeNodeViewModel treeNodeViewModel)
+        private void GetChildrenIdAndSelf(TreeNodeViewModel treeNodeViewModel, List<int> children)
         {
-            for (int i = 0; i < treeNodeViewModel.Children.Count; ++i)
+            children.Add(treeNodeViewModel.Id);
+            this.GetAllChildrenId(treeNodeViewModel, children);
+        }
+
+        private void GetAllChildrenId(TreeNodeViewModel treeNodeViewModel, List<int> children)
+        {
+            foreach (int childId in treeNodeViewModel.Children)
             {
-                TreeNodeViewModel child = this.Get(treeNodeViewModel.Children[i]);
-                this.RecursionRemove(child);
+                TreeNodeViewModel child = this.Get(childId);
+                children.Add(child.Id);
+                this.GetAllChildrenId(child, children);
             }
-            this.treeNodeDict.Remove(treeNodeViewModel.Id);
-            this.treeNodes.Remove(treeNodeViewModel);
         }
 
         public void Remove(TreeNodeViewModel treeNodeViewModel)
         {
-            this.RecursionRemove(treeNodeViewModel);
-            if (treeNodeViewModel.Parent != null)
+            List<int> allId = new List<int>();
+            this.GetChildrenIdAndSelf(treeNodeViewModel, allId);
+
+            foreach (int childId in allId)
+            {
+                TreeNodeViewModel child = this.Get(childId);
+                this.treeNodes.Remove(child);
+                this.treeNodes.Remove(treeNodeViewModel);
+            }
+
+            TreeNodeViewModel parent = treeNodeViewModel.Parent;
+            if (parent != null)
             {
-                treeNodeViewModel.Parent.Children.Remove(treeNodeViewModel.Id);
+                parent.Children.Remove(treeNodeViewModel.Id);
             }
+
             var treeLayout = new TreeLayout(this);
             treeLayout.ExcuteLayout(this.Root);
         }
@@ -136,12 +166,12 @@ namespace Modules.Tree
                 tmpNode = tmpNode.Parent;
             }
 
-            if (from.IsFolder)
+            if (from.IsFold)
             {
                 this.UnFold(from);
             }
 
-            if (to.IsFolder)
+            if (to.IsFold)
             {
                 this.UnFold(to);
             }
@@ -158,12 +188,17 @@ namespace Modules.Tree
         /// <param name="treeNodeViewModel"></param>
         public void Fold(TreeNodeViewModel treeNodeViewModel)
         {
-            foreach (var childId in treeNodeViewModel.Children)
+            List<int> allChildId = new List<int>();
+            this.GetAllChildrenId(treeNodeViewModel, allChildId);
+
+            foreach (int childId in allChildId)
             {
                 TreeNodeViewModel child = this.Get(childId);
-                this.RecursionRemove(child);
+                this.treeNodes.Remove(child);
             }
-            treeNodeViewModel.IsFolder = true;
+
+            treeNodeViewModel.IsFold = true;
+
             var treeLayout = new TreeLayout(this);
             treeLayout.ExcuteLayout(this.Root);
         }
@@ -171,36 +206,22 @@ namespace Modules.Tree
         /// <summary>
         /// 展开节点,一级一级展开,一次只展开下层子节点,比如下层节点是折叠的,那下下层节点不展开
         /// </summary>
-        /// <param name="unFoldNode"></param>
-        public void UnFold(TreeNodeViewModel unFoldNode)
+        /// <param name="treeNodeViewModel"></param>
+        public void UnFold(TreeNodeViewModel treeNodeViewModel)
         {
-            foreach (var childId in unFoldNode.Children)
-            {
-                TreeNodeViewModel child = this.Get(childId);
-                this.RecursionAdd(child);
-            }
-            unFoldNode.IsFolder = false;
-            var treeLayout = new TreeLayout(this);
-            treeLayout.ExcuteLayout(this.Root);
-        }
+            treeNodeViewModel.IsFold = false;
 
-        private void RecursionAdd(TreeNodeViewModel treeNodeViewModel)
-        {
-            if (!this.treeNodes.Contains(treeNodeViewModel))
-            {
-                this.treeNodes.Add(treeNodeViewModel);
-            }
-            List<int> children = treeNodeViewModel.Children;
+            List<int> allChildId = new List<int>();
+            this.GetAllChildrenId(treeNodeViewModel, allChildId);
 
-            if (treeNodeViewModel.IsFolder)
-            {
-                return;
-            }
-            foreach (var childId in children)
+            foreach (int childId in allChildId)
             {
                 TreeNodeViewModel child = this.Get(childId);
-                this.RecursionAdd(child);
+                this.treeNodes.Add(child);
             }
+
+            var treeLayout = new TreeLayout(this);
+            treeLayout.ExcuteLayout(this.Root);
         }
     }
 }