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. WPF
  4. NavigationControl - Part 3

NavigationControl - Part 3

Scheduled Pinned Locked Moved WPF
comcollaborationhelpquestion
3 Posts 2 Posters 11 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
    Kevin Marois
    wrote on last edited by
    #1

    So I am continuing to work on my Navigation Control[^]. See this[^] and this[^]. The code is in this repo[^]. Special thanks to Richard Deeming for all your help so far. I've learned alot from you. If you look at the image of the control in the first link above, you 'll see 3 sections, with the 3rd still loading. The expanders can be openend either by the user, or by saving & restoring a bool. On the NavigationPane control there's a DP called IsPaneExpanded. This get called with from the user or by the restoring during load. When the control is being initialized I store the value of the DP. Fields

    // Stores the value of the DP IsPaneExpanded during initialization. See
    // comments in the DP IsPaneExpanded
    private bool _isPaneExpanded = false;

    // Set to true after the control has finished initializing
    private bool _isInitialized = false;

    IsPaneExpanded DP

    public static readonly DependencyProperty IsPaneExpandedProperty =
    DependencyProperty.Register("IsPaneExpanded",
    typeof(bool),
    typeof(NavigationPane),
    new PropertyMetadata(false, new PropertyChangedCallback(OnIsPaneExpandedChanged)));

    public bool IsPaneExpanded
    {
    get { return (bool)GetValue(IsPaneExpandedProperty); }
    set { SetValue(IsPaneExpandedProperty, value); }
    }

    private static async void OnIsPaneExpandedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
    var control = (NavigationPane)d;

    if (!control.\_isInitialized)
    {
        // If here, the control is still being initialized. Store the
        // IsPaneExpanded setting for later use when the control's init
        // has finished
        control.\_isPaneExpanded = control.IsPaneExpanded;
    
        // Since the control is not loaded, there is nothing to show. But
    
    Richard DeemingR 1 Reply Last reply
    0
    • K Kevin Marois

      So I am continuing to work on my Navigation Control[^]. See this[^] and this[^]. The code is in this repo[^]. Special thanks to Richard Deeming for all your help so far. I've learned alot from you. If you look at the image of the control in the first link above, you 'll see 3 sections, with the 3rd still loading. The expanders can be openend either by the user, or by saving & restoring a bool. On the NavigationPane control there's a DP called IsPaneExpanded. This get called with from the user or by the restoring during load. When the control is being initialized I store the value of the DP. Fields

      // Stores the value of the DP IsPaneExpanded during initialization. See
      // comments in the DP IsPaneExpanded
      private bool _isPaneExpanded = false;

      // Set to true after the control has finished initializing
      private bool _isInitialized = false;

      IsPaneExpanded DP

      public static readonly DependencyProperty IsPaneExpandedProperty =
      DependencyProperty.Register("IsPaneExpanded",
      typeof(bool),
      typeof(NavigationPane),
      new PropertyMetadata(false, new PropertyChangedCallback(OnIsPaneExpandedChanged)));

      public bool IsPaneExpanded
      {
      get { return (bool)GetValue(IsPaneExpandedProperty); }
      set { SetValue(IsPaneExpandedProperty, value); }
      }

      private static async void OnIsPaneExpandedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
      {
      var control = (NavigationPane)d;

      if (!control.\_isInitialized)
      {
          // If here, the control is still being initialized. Store the
          // IsPaneExpanded setting for later use when the control's init
          // has finished
          control.\_isPaneExpanded = control.IsPaneExpanded;
      
          // Since the control is not loaded, there is nothing to show. But
      
      Richard DeemingR Offline
      Richard DeemingR Offline
      Richard Deeming
      wrote on last edited by
      #2

      Problem 1: The change event for the IsPaneExpanded property sets the IsPaneExpanded property to false if _isInitialized is false. If the property has just changed to true, that will cause the change event to fire again. As a result, the _isPaneExpanded field will be set to true, then immediately set back to false. Thankfully, WPF won't fire the event if the property is set to the same value; otherwise, you'd end up with infinite recursion. It would probably be better to use a CoerceValueCallback[^] instead:

      public static readonly DependencyProperty IsPaneExpandedProperty =
      DependencyProperty.Register("IsPaneExpanded",
      typeof(bool),
      typeof(NavigationPane),
      new PropertyMetadata(
      defaultValue: false,
      propertyChangedCallback: new PropertyChangedCallback(OnIsPaneExpandedChanged),
      coerceValueCallback: new CoerceValueCallback(CoerceIsPaneExpanded)
      ));

      private static void OnIsPaneExpandedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
      {
      var control = (NavigationPane)d;
      control._isPaneExpanded = (bool)e.NewValue;
      control.CoerceValue(IsPaneExpandedProperty);

      if (control.\_isInitialized && control.\_isPaneExpanded)
      {
          \_ = control.Load();
      }
      

      }

      private static object CoerceIsPaneExpanded(DependencyObject d, object baseValue)
      {
      var control = (NavigationPane)d;
      return control._isInitialized ? baseValue : (object)false;
      }

      Problem 2: You need to change the _isInitialized field, trigger the change event for the IsPaneExpanded property, then load the data.

      private void NavigationPane_Initialized(object? sender, EventArgs e)
      {
      _isInitialized = true;
      CoerceValue(IsPaneExpandedProperty);

      if (\_isPaneExpanded)
      {
          \_ = Load();
      }
      

      }


      "These people looked deep within my soul and assigned me a number based on the order in which I joined." - H

      "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

      K 1 Reply Last reply
      0
      • Richard DeemingR Richard Deeming

        Problem 1: The change event for the IsPaneExpanded property sets the IsPaneExpanded property to false if _isInitialized is false. If the property has just changed to true, that will cause the change event to fire again. As a result, the _isPaneExpanded field will be set to true, then immediately set back to false. Thankfully, WPF won't fire the event if the property is set to the same value; otherwise, you'd end up with infinite recursion. It would probably be better to use a CoerceValueCallback[^] instead:

        public static readonly DependencyProperty IsPaneExpandedProperty =
        DependencyProperty.Register("IsPaneExpanded",
        typeof(bool),
        typeof(NavigationPane),
        new PropertyMetadata(
        defaultValue: false,
        propertyChangedCallback: new PropertyChangedCallback(OnIsPaneExpandedChanged),
        coerceValueCallback: new CoerceValueCallback(CoerceIsPaneExpanded)
        ));

        private static void OnIsPaneExpandedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
        var control = (NavigationPane)d;
        control._isPaneExpanded = (bool)e.NewValue;
        control.CoerceValue(IsPaneExpandedProperty);

        if (control.\_isInitialized && control.\_isPaneExpanded)
        {
            \_ = control.Load();
        }
        

        }

        private static object CoerceIsPaneExpanded(DependencyObject d, object baseValue)
        {
        var control = (NavigationPane)d;
        return control._isInitialized ? baseValue : (object)false;
        }

        Problem 2: You need to change the _isInitialized field, trigger the change event for the IsPaneExpanded property, then load the data.

        private void NavigationPane_Initialized(object? sender, EventArgs e)
        {
        _isInitialized = true;
        CoerceValue(IsPaneExpandedProperty);

        if (\_isPaneExpanded)
        {
            \_ = Load();
        }
        

        }


        "These people looked deep within my soul and assigned me a number based on the order in which I joined." - H

        K Offline
        K Offline
        Kevin Marois
        wrote on last edited by
        #3

        Thanks, I understand the change you recommened, but it doesn't seem to change anything. I have two different issues. I beleive I solved the first one. 1. The Projects pane should be expanded on startup BEFORE it loads so the user seees the wait indicator. This bit of code in the MainWindow simulates storing and resetting it from settings later on. if there was an ExpandedExpanded (past-tense) then I could call Load() from there. Main Window.cs

        NavigationPaneInfos = new List
        {
        new NavigationPaneModel
        {
        Header = "Projects",
        NavigationItemType = NavigationItemType.Project,
        DataSource = Functional.Apply(Repository.GetNavigationItems, NavigationItemType.Project),
        IsExpanded = true // <====== 1. This should force the Projects pane to expand on startup, and that should trigger Load() after the wait indicator is visible
        },

        new NavigationPaneModel
        {
            Header = "Inventory", 
            NavigationItemType = NavigationItemType.Inventory,
            DataSource = Functional.Apply(Repository.GetNavigationItems, NavigationItemType.Inventory),
        },
        
        new NavigationPaneModel
        {
            Header = "Companies" , 
            NavigationItemType = NavigationItemType.Company,
            DataSource = Functional.Apply(Repository.GetNavigationItems, NavigationItemType.Company),
        },
        
        new NavigationPaneModel
        {
            Header = "Employees", 
            NavigationItemType = NavigationItemType.Employee,
            DataSource = Functional.Apply(Repository.GetNavigationItems, NavigationItemType.Employee),
        }
        

        };

        so, that caused this

        private static object CoerceIsPaneExpanded(DependencyObject d, object baseValue)
        {
        var control = (NavigationPane)d;
        var newVal = control._isInitialized ? baseValue : (object)false;
        return newVal; //<======= THIS IS NEVER TRUE
        }

        and

            private void NavigationPane\_Initialized(object? sender, EventArgs e)
            {
                \_isInitialized = true;
                CoerceValue(IsPaneExpandedProperty);
        
                if (\_isPaneExpanded) //<====== 2. THIS IS NEVER TRUE
                {
                    \_ = Load();
                }
            }
        

        so, I added this, which correctly sets _isPaneExpanded based off the value set in the main window

        private static async void OnNavigationPaneModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
        var control = (NavigationPane)d;
        var model = e.NewValue as N

        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