WPF: How to make a textbox dynamically sized yet prevent autosizing? WPF: How to make a textbox dynamically sized yet prevent autosizing? wpf wpf

WPF: How to make a textbox dynamically sized yet prevent autosizing?


Scrollable-expandable-controls problem.

Scrollable-expandable-controls : are controls that can stretch as its content grows and will display scrollbars when their size is restricted.

Problem appears when they are located inside another scrollable control. Child scrollable-expandable-controls will keep expanding and will count on the outer scrollable control's scrollbars.

if you give it a maximum width or height problem will be resolved but you will need to know the size ahead and you don't have this privilege if you want a dynamic app that works well with all different screen sizes.

in order to achieve required behavior , we need a panel in between to allow its children (scrollable-expandable-control) to grow asking them to give the minimum required size and then give them the maxiumum size the parent provides without displaying scrollbars , currently there is no panel like this.

Here is a one that I developed to provide this functionality:

    class LimitChild : System.Windows.Controls.Panel    {        public LimitChild()        {        }        protected override Size MeasureOverride(System.Windows.Size availableSize)        {            System.Diagnostics.Debug.Assert(InternalChildren.Count == 1);            System.Windows.UIElement child = InternalChildren[0];            Size panelDesiredSize = new Size();            // panelDesiredSize.Width = availableSize.Width;            panelDesiredSize.Width = (double)child.GetValue(FrameworkElement.MinWidthProperty);            panelDesiredSize.Height = (double)child.GetValue(FrameworkElement.MinHeightProperty);            child.Measure(panelDesiredSize);            // IMPORTANT: do not allow PositiveInfinity to be returned, that will raise an exception in the caller!             // PositiveInfinity might be an availableSize input; this means that the parent does not care about sizing             return panelDesiredSize;        }        protected override System.Windows.Size ArrangeOverride(System.Windows.Size finalSize)        {            System.Windows.UIElement child = InternalChildren[0];            child.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));            if (finalSize.Width > child.RenderSize.Width)                finalSize.Width = child.RenderSize.Width;            if (finalSize.Height > child.RenderSize.Height)                finalSize.Height = child.RenderSize.Height;            return finalSize; // Returns the final Arranged size        }    }

and then inside your xaml incapsulate your scrollable-expandable-control in it.

        <l:LimitChild            Grid.Row="1">            <TextBox                VerticalScrollBarVisibility="Auto"                HorizontalScrollBarVisibility="Auto"                MinHeight="200"                AcceptsReturn="True">Test</TextBox>        </l:LimitChild>


Try this:

<Window x:Class="WpfApplication1.Window1"    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    Title="Window1" Height="300" Width="300">    <Grid>        <Grid.RowDefinitions>            <RowDefinition Height="Auto" />            <RowDefinition Height="*" />        </Grid.RowDefinitions>        <TextBox />        <TextBox AcceptsReturn="True" Grid.Row="1" VerticalScrollBarVisibility="Auto" />    </Grid></Window>

This should exactly meet your requirements.


Actually you can bind to ActualHeight by accessing ancestor using RelativeSource binding:

Height="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}},                 Path=RowDefinitions[1].ActualHeight}"


Update:

If you what that scroll bar should be shown only for second TextBox - put ScrollViewer only for it:

    <Grid>        <Grid.RowDefinitions>           <RowDefinition Height="Auto" />           <RowDefinition Height="*" />        </Grid.RowDefinitions>        <TextBox>Test</TextBox>        <ScrollViewer Grid.Row="1">                            <TextBox MinHeight="100" AcceptsReturn="True" >Test</TextBox>                        </ScrollViewer>    </Grid>