Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Combining TreeView and Canvas in WPF ( MVVM )

Combining TreeView and Canvas in WPF ( MVVM )

Scheduled Pinned Locked Moved C#
wpfcsharparchitecturehelpquestion
8 Posts 3 Posters 3 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Offline
    K Offline
    Kenneth Haugland
    wrote on last edited by
    #1

    I many projects I have had a similar type of problem that I have not found a good general solution to. Assuming that I have many different lines on a Canvas that are all organized in the flat storage Canvas.Children but I want these lines to be grouped by the object they are trying to draw. Like all lines in a Ball is grouped together and can be removed by a single checkbox click and at a higher level, I can remove the entire football field etc. The only way I found out to do this was through looping through everything every time I was adding, changing and removing it, basically involving recursion. Does anyone have some good ideas or practices for solving this?

    P L 2 Replies Last reply
    0
    • K Kenneth Haugland

      I many projects I have had a similar type of problem that I have not found a good general solution to. Assuming that I have many different lines on a Canvas that are all organized in the flat storage Canvas.Children but I want these lines to be grouped by the object they are trying to draw. Like all lines in a Ball is grouped together and can be removed by a single checkbox click and at a higher level, I can remove the entire football field etc. The only way I found out to do this was through looping through everything every time I was adding, changing and removing it, basically involving recursion. Does anyone have some good ideas or practices for solving this?

      P Offline
      P Offline
      Pete OHanlon
      wrote on last edited by
      #2

      I would normally base this type of thing on working with an underlying model using MVVM. Basically, I would have something like a Shape model which contained an ObservableCollection of Lines. All you would need to do then is remove the Shape and clear the Lines collection and the related items would be removed from the screen. Without seeing your code, I can't say whether or not this is feasible with the architecture you currently have in place.

      This space for rent

      K 1 Reply Last reply
      0
      • P Pete OHanlon

        I would normally base this type of thing on working with an underlying model using MVVM. Basically, I would have something like a Shape model which contained an ObservableCollection of Lines. All you would need to do then is remove the Shape and clear the Lines collection and the related items would be removed from the screen. Without seeing your code, I can't say whether or not this is feasible with the architecture you currently have in place.

        This space for rent

        K Offline
        K Offline
        Kenneth Haugland
        wrote on last edited by
        #3

        At the lowest level, I have a class that inherits FrameWorkElement and use drawing visuals to actually render the objects. This is because I don't only have lines but Bezier curves etc. The problem was that I wanted to group things at an arbitrary deep levels MyDrawingFile -Road --Car ---Wheels ----Rims ----Tires ---Lights -----StopLights -----HeadLights ---Windows -House So if I wanted to disable everything but the House I basically had to traverse all the objects and its children under the ObservableCollection and then manually remove the objects in the Canvas. I basically set up something like:

        public abstract class HierarchyBase : INotifyPropertyChanged
        {

            private ObservableCollection children = new ObservableCollection();
        
            public ObservableCollection Children
            {
                get { return children; }
                set { children = value; }
            }
        
        
            public string Name { get; set; }
        
            private bool pIsEnabled;
            public bool IsEnabled
            {
                get { return pIsEnabled; }
                set { pIsEnabled = value;
                    StateUpdated();
                    OnPropertyChanged();
                }
            }
        
            private bool pIsVisible;
        
            public bool IsVisible
            {
                get { return pIsVisible; }
                set {
                    pIsVisible = value;
                    StateUpdated();
                    OnPropertyChanged();
                }
            }
        
            private void StateUpdated()
            {
                if (this is IDrawing)
                {                
                    ((IDrawing)this).Redraw(IsVisible);
                }            
        
                foreach (HierarchyBase child in Children)
                {
                    if (!this.IsEnabled || !this.IsVisible)
                    {
                        child.IsVisible = false;
                    }
                }
            }
        
            public event PropertyChangedEventHandler PropertyChanged;
            
            private void OnPropertyChanged(\[CallerMemberName\]string caller = "")
            {
                // make sure only to call this if the value actually changes
        
                var handler = PropertyChanged;
                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(caller));
                    StateUpdated();
                }
            }
        }
        

        But then binding was a

        1 Reply Last reply
        0
        • K Kenneth Haugland

          I many projects I have had a similar type of problem that I have not found a good general solution to. Assuming that I have many different lines on a Canvas that are all organized in the flat storage Canvas.Children but I want these lines to be grouped by the object they are trying to draw. Like all lines in a Ball is grouped together and can be removed by a single checkbox click and at a higher level, I can remove the entire football field etc. The only way I found out to do this was through looping through everything every time I was adding, changing and removing it, basically involving recursion. Does anyone have some good ideas or practices for solving this?

          L Offline
          L Offline
          Lost User
          wrote on last edited by
          #4

          List Ball = ... ... Canvas.Children.Add( line ); Ball.Add( line ); ... Ball.ForEach( l => Canvas.Children.Remove( l as UIElement ) );

          "(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal

          K 1 Reply Last reply
          0
          • L Lost User

            List Ball = ... ... Canvas.Children.Add( line ); Ball.Add( line ); ... Ball.ForEach( l => Canvas.Children.Remove( l as UIElement ) );

            "(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal

            K Offline
            K Offline
            Kenneth Haugland
            wrote on last edited by
            #5

            Yes, something like this is what I tried to do, but I found it to be very messy. No binding and I have to resort to storing the connection to a canvas in the code behind. It does work but not really good MVVM?

            L 1 Reply Last reply
            0
            • K Kenneth Haugland

              Yes, something like this is what I tried to do, but I found it to be very messy. No binding and I have to resort to storing the connection to a canvas in the code behind. It does work but not really good MVVM?

              L Offline
              L Offline
              Lost User
              wrote on last edited by
              #6

              It's a generic "infrastructure" helper "pattern"; nothing to do with "MVVM". Plumbing.

              "(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal

              K 1 Reply Last reply
              0
              • L Lost User

                It's a generic "infrastructure" helper "pattern"; nothing to do with "MVVM". Plumbing.

                "(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal

                K Offline
                K Offline
                Kenneth Haugland
                wrote on last edited by
                #7

                Not initially no. But as soon as I had the treeview up and running with binding:

                This was very neat, but now how to bind the canvas to the code behind? I thought this was very messy.

                public abstract class HierarchyBase : INotifyPropertyChanged
                {
                public HierarchyBase()
                {
                Delete = new RelayCommand( CanDelete, DeleteThis);
                children.CollectionChanged +=ItemChildren_CollectionChanged;
                }

                    public Canvas myCanvas;
                    private HierarchyBase \_parent;
                
                    private void ItemChildren\_CollectionChanged(object sender,NotifyCollectionChangedEventArgs e)
                    {
                        //different kind of changes that may have occurred in collection
                        if (e.Action == NotifyCollectionChangedAction.Add)
                        {
                            foreach (var item in e.NewItems)
                            {
                                ((HierarchyBase)item).\_parent = this;
                                ((HierarchyBase)item).myCanvas = this.myCanvas;
                            }
                            //((List)e.NewItems).ForEach(i => ((HierarchyBase)i).\_parent = this); // foreach (e.NewItems)(i => i;)
                
                        }
                        if (e.Action == NotifyCollectionChangedAction.Replace)
                        {
                            //your code
                        }
                        if (e.Action == NotifyCollectionChangedAction.Remove)
                        {
                            foreach (var item   in e.OldItems)
                            {
                                ((HierarchyBase)item).\_parent = null;
                                ((HierarchyBase)item).myCanvas = null;
                            }
                        }
                        if (e.Action == NotifyCollectionChangedAction.Move)
                        {
                            //your code
                        }
                    }
                
                    private ObservableCollection children = new ObservableCollection();
                
                
                    public ObservableCollection Children
                    {
                        get { return children; }
                        set { children = value; }
                    }
                
                    public ICommand Delete { get; set; }
                
                    private bool CanDelete(object obj)
                    {
                        return IsEnabled;
                    }
                
                    private void DeleteThi
                
                L 1 Reply Last reply
                0
                • K Kenneth Haugland

                  Not initially no. But as soon as I had the treeview up and running with binding:

                  This was very neat, but now how to bind the canvas to the code behind? I thought this was very messy.

                  public abstract class HierarchyBase : INotifyPropertyChanged
                  {
                  public HierarchyBase()
                  {
                  Delete = new RelayCommand( CanDelete, DeleteThis);
                  children.CollectionChanged +=ItemChildren_CollectionChanged;
                  }

                      public Canvas myCanvas;
                      private HierarchyBase \_parent;
                  
                      private void ItemChildren\_CollectionChanged(object sender,NotifyCollectionChangedEventArgs e)
                      {
                          //different kind of changes that may have occurred in collection
                          if (e.Action == NotifyCollectionChangedAction.Add)
                          {
                              foreach (var item in e.NewItems)
                              {
                                  ((HierarchyBase)item).\_parent = this;
                                  ((HierarchyBase)item).myCanvas = this.myCanvas;
                              }
                              //((List)e.NewItems).ForEach(i => ((HierarchyBase)i).\_parent = this); // foreach (e.NewItems)(i => i;)
                  
                          }
                          if (e.Action == NotifyCollectionChangedAction.Replace)
                          {
                              //your code
                          }
                          if (e.Action == NotifyCollectionChangedAction.Remove)
                          {
                              foreach (var item   in e.OldItems)
                              {
                                  ((HierarchyBase)item).\_parent = null;
                                  ((HierarchyBase)item).myCanvas = null;
                              }
                          }
                          if (e.Action == NotifyCollectionChangedAction.Move)
                          {
                              //your code
                          }
                      }
                  
                      private ObservableCollection children = new ObservableCollection();
                  
                  
                      public ObservableCollection Children
                      {
                          get { return children; }
                          set { children = value; }
                      }
                  
                      public ICommand Delete { get; set; }
                  
                      private bool CanDelete(object obj)
                      {
                          return IsEnabled;
                      }
                  
                      private void DeleteThi
                  
                  L Offline
                  L Offline
                  Lost User
                  wrote on last edited by
                  #8

                  What we are doing is "shadowing"; we are just going about it in different ways depending on the circumstances. Your "hierarchyBase" is "view" support code; in particular, Canvas; infrastructure code. Not sure how your "tree" relates to your earlier "ball"; so I can't visualize or comment on it. Your architecture is "component based" (versus "view" based); or "views with components"; it should use appropriate patterns. I would consider integrating with Unity.

                  "(I) am amazed to see myself here rather than there ... now rather than then". ― Blaise Pascal

                  1 Reply Last reply
                  0
                  Reply
                  • Reply as topic
                  Log in to reply
                  • Oldest to Newest
                  • Newest to Oldest
                  • Most Votes


                  • Login

                  • Don't have an account? Register

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • World
                  • Users
                  • Groups