<Grid> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <Canvas Name="MainCanvas"> <StackPanel x:Name="StackWorks"></StackPanel> </Canvas> <ListView x:Name="ListUsers" Grid.Column="1"> <ListView.ItemTemplate> <DataTemplate> <StackPanel> <TextBlock Text="{Binding Name}"></TextBlock> <TextBlock Text="{Binding Work.Name}"></TextBlock> </StackPanel> </DataTemplate> </ListView.ItemTemplate> </ListView> </Grid>
Work contextWork; List<StackPanel> stackPanels; Stack<TextBlock> textBlocks; List<User> users; public UserTree() { InitializeComponent(); contextWork = App.DB.Works.FirstOrDefault(); Refresh(); } private void Refresh() { stackPanels = new List<StackPanel>(); textBlocks = new Stack<TextBlock>(); users = new List<User>(); StackWorks.Children.Clear(); var work = App.DB.Works.FirstOrDefault(); GenerateTree(work, 0, contextWork); GenerateUsers(contextWork); ListUsers.ItemsSource = users; } private void GenerateUsers(Work work) { var usersDown = App.DB.Users.Where(x => (x.Work != null && x.Work.Id == work.Id)).ToList(); users.AddRange(usersDown); var works = App.DB.Works.Where(x => (x.LiderWork != null && x.LiderWork.Id == work.Id)).ToList(); foreach (var workDown in works) GenerateUsers(workDown); } private void GenerateTree(Work work, int level, Work targetWork) { var works = App.DB.Works.Where(x => (x.LiderWork != null && x.LiderWork.Id == work.Id)).ToList(); if (stackPanels.Count() <= level) { stackPanels.Add(new StackPanel() { Orientation = Orientation.Horizontal, HorizontalAlignment = HorizontalAlignment.Center, }); StackWorks.Children.Add(stackPanels[level]); } var textBlock = new TextBlock() { Text = work.Name, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, Margin = new Thickness(10), Background = Brushes.LightGreen, Padding = new Thickness(5), DataContext = work, }; stackPanels[level].Children.Add(textBlock); textBlock.MouseDown += TextBlock_MouseDown; if (work.Id == targetWork.Id) textBlock.Background = Brushes.Green; if (work.Id != 1) GetLine(textBlock, textBlocks.Peek()); textBlocks.Push(textBlock); foreach(var workDown in works) GenerateTree(workDown, level + 1, targetWork); textBlocks.Pop(); } private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e) { var work = (sender as TextBlock).DataContext as Work; if (work == null) return; contextWork = work; Refresh(); } private void GetLine(TextBlock textBlock1, TextBlock textBlock2) { var line = new Line() { Stroke = Brushes.Black, StrokeThickness = 2, }; var triangle = new Polygon() { Fill = Brushes.Black, Stroke = Brushes.Black, StrokeThickness = 2, }; CompositionTarget.Rendering += (s, e) => { var point1 = textBlock1.TranslatePoint(new Point(textBlock1.ActualWidth / 2, textBlock1.ActualHeight / 2 - 10), MainCanvas); var point2 = textBlock2.TranslatePoint(new Point(textBlock2.ActualWidth / 2, textBlock2.ActualHeight / 2 + 10), MainCanvas); line.X1 = point1.X; line.Y1 = point1.Y - 10; line.X2 = point2.X; line.Y2 = point2.Y; triangle.Points = new PointCollection() { new Point(point1.X + 10, point1.Y - 10), new Point(point1.X - 10, point1.Y - 10), new Point(point1.X, point1.Y), }; }; if (!MainCanvas.Children.Contains(line)) MainCanvas.Children.Add(line); if (!MainCanvas.Children.Contains(triangle)) MainCanvas.Children.Add(triangle); }