Nested Scroll Areas

前端 未结 7 540
失恋的感觉
失恋的感觉 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:

    <ScrollViewer>
        <StackPanel Orientation="Vertical">
            <Whatever />
    
            <decorators:RestrictDesiredSizeDecorator MinWidth="100" KeepHeight="True">
                <TextBox
                    Text="{Binding Comment, UpdateSourceTrigger=PropertyChanged}"
                    Height="Auto"
                    MaxHeight="360"
                    VerticalScrollBarVisibility="Auto"
                    HorizontalScrollBarVisibility="Auto"
                    AcceptsReturn="True"
                    AcceptsTab="True"
                    TextWrapping="WrapWithOverflow"
                    />
            </decorators:RestrictDesiredSizeDecorator>
    
            <Whatever />
        </StackPanel>
    </ScrollViewer
    

    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.

    0 讨论(0)
提交回复
热议问题