I’m still working on Quill, but I figured this construct was useful enough for me to save in its
purest form, before I uglify it with orientation hacks.
This is an implementation of a properly-behaving multiline TextBox for Windows Phone. The original implementation
was sourced from KlingDigital.
I just made extremely minor modifications, mostly refactoring to make it easier to modify (adding an input scope,
supporting landscape, etc).
<phone:PhoneApplicationPagex:Class="Autocomplete.MainPage"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"mc:Ignorable="d"FontFamily="{StaticResource PhoneFontFamilyNormal}"FontSize="{StaticResource PhoneFontSizeNormal}"Foreground="{StaticResource PhoneForegroundBrush}"SupportedOrientations="Portrait"Orientation="Portrait"shell:SystemTray.IsVisible="True"Loaded="PhoneApplicationPage_Loaded"><!--LayoutRoot is the root grid where all page content is placed--><Gridx:Name="LayoutRoot"Background="Transparent"><Grid.RowDefinitions><RowDefinition/><RowDefinitionHeight="Auto"/></Grid.RowDefinitions><ScrollViewerx:Name="Scroller"Background="#1ba1e2"Grid.Row="0"><StackPanelVerticalAlignment="Top"><TextBoxx:Name="ScrollerInput"TextWrapping="Wrap"AcceptsReturn="True"TextChanged="ScrollerInput_TextChanged"GotFocus="ScrollerInput_GotFocus"LostFocus="ScrollerInput_LostFocus"Tap="ScrollerInput_Tap"/></StackPanel></ScrollViewer><Gridx:Name="KeyboardPlaceholder"Grid.Row="1"Visibility="Collapsed"/></Grid></phone:PhoneApplicationPage>
usingMicrosoft.Phone.Controls;usingSystem.Windows;usingSystem.Windows.Controls;usingSystem.Windows.Media;namespaceAutocomplete{publicpartialclassMainPage:PhoneApplicationPage{privateconstintPortraitHeight=336;privatedouble_inputHeight=0;privatedouble_tapHeight=0;// ConstructorpublicMainPage(){InitializeComponent();}privatevoidSizePlaceholder(){KeyboardPlaceholder.Height=PortraitHeight;}privatevoidForceLayout(){App.RootFrame.RenderTransform=newCompositeTransform();LayoutRoot.UpdateLayout();}privatevoidPhoneApplicationPage_Loaded(objectsender,RoutedEventArgse){}privatevoidScrollerInput_TextChanged(objectsender,TextChangedEventArgse){// updates seem to be late if we don't invoke them with the dispatcherDispatcher.BeginInvoke(()=>{doublecurrentInputHeight=ScrollerInput.ActualHeight;if(currentInputHeight>_inputHeight){// scroll up by the difference between the current box size and the old box sizeScroller.ScrollToVerticalOffset(Scroller.VerticalOffset+currentInputHeight-_inputHeight);}_inputHeight=currentInputHeight;});}privatevoidScrollerInput_GotFocus(objectsender,RoutedEventArgse){KeyboardPlaceholder.Visibility=Visibility.Visible;SizePlaceholder();ForceLayout();Scroller.ScrollToVerticalOffset(_tapHeight);}privatevoidScrollerInput_LostFocus(objectsender,RoutedEventArgse){KeyboardPlaceholder.Visibility=Visibility.Collapsed;}privatevoidScrollerInput_Tap(objectsender,System.Windows.Input.GestureEventArgse){_tapHeight=e.GetPosition(ScrollerInput).Y-120;}}}
Hopefully this template will prove useful in the future.