Make WPF/SL grid ignore a child element when determining size

后端 未结 2 868
無奈伤痛
無奈伤痛 2020-12-19 12:32

I have a Grid which has several children, one of which is a ScrollViewer. I want the Grid to size itself based on all of its children except the ScrollViewer, which

相关标签:
2条回答
  • 2020-12-19 12:58

    Pavlo Glazkov's answer works very well for me! I have used it for a control that does not want to specify explicit sizes ... I added some logic and properties to defeat one dimension:

    public sealed class NoSizeDecorator
                : Decorator
        {
            /// <summary>
            /// Sets whether the width will be overridden.
            /// </summary>
            public static readonly DependencyProperty DisableWidthOverrideProperty
                    = DependencyProperty.Register(
                            nameof(NoSizeDecorator.DisableWidthOverride),
                            typeof(bool),
                            typeof(NoSizeDecorator),
                            new FrameworkPropertyMetadata(
                                    false,
                                    FrameworkPropertyMetadataOptions.AffectsMeasure));
    
            /// <summary>
            /// Sets whether the width will be overridden.
            /// </summary>
            public bool DisableWidthOverride
            {
                get => (bool)GetValue(NoSizeDecorator.DisableWidthOverrideProperty);
                set => SetValue(NoSizeDecorator.DisableWidthOverrideProperty, value);
            }
    
            /// <summary>
            /// Sets whether the height will be overridden.
            /// </summary>
            public static readonly DependencyProperty DisableHeightOverrideProperty
                    = DependencyProperty.Register(
                            nameof(NoSizeDecorator.DisableHeightOverride),
                            typeof(bool),
                            typeof(NoSizeDecorator),
                            new FrameworkPropertyMetadata(
                                    false,
                                    FrameworkPropertyMetadataOptions.AffectsMeasure));
    
            /// <summary>
            /// Sets whether the height will be overridden.
            /// </summary>
            public bool DisableHeightOverride
            {
                get => (bool)GetValue(NoSizeDecorator.DisableHeightOverrideProperty);
                set => SetValue(NoSizeDecorator.DisableHeightOverrideProperty, value);
            }
    
    
            protected override Size MeasureOverride(Size constraint)
            {
                UIElement child = Child;
                if (child == null)
                    return new Size();
                constraint
                        = new Size(
                                DisableWidthOverride
                                        ? constraint.Width
                                        : 0D,
                                DisableHeightOverride
                                        ? constraint.Height
                                        : 0D);
                child.Measure(constraint);
                return new Size(
                        DisableWidthOverride
                                ? child.DesiredSize.Width
                                : 0D,
                        DisableHeightOverride
                                ? child.DesiredSize.Height
                                : 0D);
            }
        }
    
    0 讨论(0)
  • 2020-12-19 13:20

    If I understood correctly what you want, then you can do the following trick. Create a decorator that will ask for 0 space during the Measure stage and will arrange the child with all the given space at the Arrange stage:

    public class NoSizeDecorator : Decorator
    {
        protected override Size MeasureOverride(Size constraint) {
            // Ask for no space
            Child.Measure(new Size(0,0));
            return new Size(0, 0);
        }        
    }
    

    And your XAML will look like this:

    <Grid x:Name="LayoutRoot" Background="White">
        <Grid VerticalAlignment="Top" HorizontalAlignment="Left">
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <my:NoSizeDecorator Grid.Row="0" Grid.Column="0">
                <ScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto">
                    <Button Height="300" Width="300" Content="0,0"/>
                </ScrollViewer>
            </my:NoSizeDecorator>
    
            <Button Grid.Row="1" Grid.Column="0" Height="100" Width="100" Content="1,0"/>
            <Button Grid.Row="0" Grid.Column="1" Height="100" Width="100" Content="0,1"/>
            <Button Grid.Row="1" Grid.Column="1" Height="100" Width="100" Content="1,1"/>
        </Grid>
    </Grid>
    
    0 讨论(0)
提交回复
热议问题