Nested Scroll Areas

前端 未结 7 560
失恋的感觉
失恋的感觉 2020-12-05 15:34

I creating a control for WPF, and I have a question for you WPF gurus out there.

I want my control to be able to expand to fit a resizable window.

In my con

7条回答
  •  死守一世寂寞
    2020-12-05 16:32

    I ended up combining Daniels answer and Heiner's answer. I decided to post the entire solution to make it easier for people to adopt this if needed. Here's my decorator class:

    public class RestrictDesiredSizeDecorator : Decorator
    {
        public static readonly DependencyProperty KeepWidth;
        public static readonly DependencyProperty KeepHeight;
    
        #region Dependency property setters and getters
        public static void SetKeepWidth(UIElement element, bool value)
        {
            element.SetValue(KeepWidth, value);
        }
    
        public static bool GetKeepWidth(UIElement element)
        {
            return (bool)element.GetValue(KeepWidth);
        }
    
        public static void SetKeepHeight(UIElement element, bool value)
        {
            element.SetValue(KeepHeight, value);
        }
    
        public static bool GetKeepHeight(UIElement element)
        {
            return (bool)element.GetValue(KeepHeight);
        }
        #endregion
    
        private Size _lastArrangeSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
    
        static RestrictDesiredSizeDecorator()
        {
            KeepWidth = DependencyProperty.RegisterAttached(
                nameof(KeepWidth),
                typeof(bool),
                typeof(RestrictDesiredSizeDecorator));
    
            KeepHeight = DependencyProperty.RegisterAttached(
                nameof(KeepHeight),
                typeof(bool),
                typeof(RestrictDesiredSizeDecorator));
        }
    
        protected override Size MeasureOverride(Size constraint)
        {
            Debug.WriteLine("Measure: " + constraint);
    
            var keepWidth = GetValue(KeepWidth) as bool? ?? false;
            var keepHeight = GetValue(KeepHeight) as bool? ?? false;
    
            var innerWidth = keepWidth ? constraint.Width : Math.Min(this._lastArrangeSize.Width, constraint.Width);
            var innerHeight = keepHeight ? constraint.Height : Math.Min(this._lastArrangeSize.Height, constraint.Height);
            base.MeasureOverride(new Size(innerWidth, innerHeight));
    
            var outerWidth = keepWidth ? Child.DesiredSize.Width : 0;
            var outerHeight = keepHeight ? Child.DesiredSize.Height : 0;
    
            return new Size(outerWidth, outerHeight);
        }
    
        protected override Size ArrangeOverride(Size arrangeSize)
        {
            Debug.WriteLine("Arrange: " + arrangeSize);
    
            if (_lastArrangeSize != arrangeSize)
            {
                _lastArrangeSize = arrangeSize;
                base.MeasureOverride(arrangeSize);
            }
    
            return base.ArrangeOverride(arrangeSize);
        }
    }
    

    and here's how I use it in the xaml:

    
        
            
    
            
                
            
    
            
        
    

    The above creates a textbox that will grow vertically (until it hits MaxHeight) but will match the parent's width without growing the outer ScrollViewer. Resizing the window/ScrollViewer to less than 100 wide will force the outer ScrollViewer to show the horizontal scroll bars. Other controls with inner ScrollViewers can be used as well, including complex grids.

提交回复
热议问题