this has yet to be defined

that is, for you

Windows Phone’s Long List Selector has an annoying problem. Its scrollbar takes up actual horizontal space on the layout grid, pushing your list items to the left. Now this normally isn’t a problem; you can just offset your list items accordingly. The problem though is that if your list ever has too few elements such that scrolling is not necessary, the scrollbar’s Visibility will be set to Collapsed and no longer take up any horizontal space, meaning that your offsets will cause your items to stick too far off of the right edge.

Here is a simple Style that you can add to a Resources file (or just a phone:PhoneApplicationPage.Resources block) that will solve this problem:


<Style x:Key="LLSFloatingScrollbarStyle"
               TargetType="phone:LongListSelector">
    <Setter Property="Background"
            Value="Transparent" />
    <Setter Property="Foreground"
            Value="{StaticResource PhoneForegroundBrush}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="phone:LongListSelector">
                <Grid Background="{TemplateBinding Background}"
                      d:DesignWidth="480"
                      d:DesignHeight="800">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="ScrollStates">
                            <VisualStateGroup.Transitions>
                                <VisualTransition GeneratedDuration="00:00:00.5" />
                            </VisualStateGroup.Transitions>
                            <VisualState x:Name="Scrolling">
                                <Storyboard>
                                    <DoubleAnimation Duration="0"
                                                     To="1"
                                                     Storyboard.TargetProperty="Opacity"
                                                     Storyboard.TargetName="VerticalScrollBar" />
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="NotScrolling" />
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Grid Margin="{TemplateBinding Padding}">

                        <ViewportControl x:Name="ViewportControl"
                                         HorizontalContentAlignment="Stretch"
                                         VerticalAlignment="Top" />

                        <ScrollBar x:Name="VerticalScrollBar"
                                   Margin="4,0,-12,0"
                                   Opacity="0"
                                   HorizontalAlignment="Right"
                                   Orientation="Vertical" />
                    </Grid>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<!-- then on your long list selector... -->

<phone:LongListSelector Style="{StaticResource LLSFloatingScrollbarStyle}" />

What this will do is cause the scrollbar to float on top of the long list selector instead of taking up horizontal space, which means that it will never push the list’s content to the left. A note though: take heed of the Margin attribute of the Scrollbar tag. You may need to adjust this to get the scrollbar to go to where you want. I personally like my scrollbars flush against the right side of the screen.

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).

Here is the XAML:

<phone:PhoneApplicationPage
    x: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-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <ScrollViewer x:Name="Scroller"
                      Background="#1ba1e2"
                      Grid.Row="0">
            <StackPanel VerticalAlignment="Top">
                <TextBox x:Name="ScrollerInput"
                         TextWrapping="Wrap"
                         AcceptsReturn="True"
                         TextChanged="ScrollerInput_TextChanged"
                         GotFocus="ScrollerInput_GotFocus"
                         LostFocus="ScrollerInput_LostFocus"
                         Tap="ScrollerInput_Tap"/>
            </StackPanel>
        </ScrollViewer>

        <Grid x:Name="KeyboardPlaceholder"
              Grid.Row="1"
              Visibility="Collapsed" />
    </Grid>    

</phone:PhoneApplicationPage>

and here is the codebehind:

using Microsoft.Phone.Controls;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Autocomplete
{
  public partial class MainPage : PhoneApplicationPage
  {
    private const int PortraitHeight = 336;

    private double _inputHeight = 0;
    private double _tapHeight = 0;

    // Constructor
    public MainPage()
    {
      InitializeComponent();
    }

    private void SizePlaceholder()
    {
      KeyboardPlaceholder.Height = PortraitHeight;
    }

    private void ForceLayout()
    {
      App.RootFrame.RenderTransform = new CompositeTransform();

      LayoutRoot.UpdateLayout();
    }

    private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
    {

    }

    private void ScrollerInput_TextChanged(object sender, TextChangedEventArgs e)
    {
      // updates seem to be late if we don't invoke them with the dispatcher
      Dispatcher.BeginInvoke(() =>
      {
        double currentInputHeight = ScrollerInput.ActualHeight;

        if (currentInputHeight > _inputHeight)
        {
          // scroll up by the difference between the current box size and the old box size
          Scroller.ScrollToVerticalOffset(Scroller.VerticalOffset + currentInputHeight - _inputHeight);
        }

        _inputHeight = currentInputHeight;
      });
    }

    private void ScrollerInput_GotFocus(object sender, RoutedEventArgs e)
    {
      KeyboardPlaceholder.Visibility = Visibility.Visible;
      SizePlaceholder();

      ForceLayout();

      Scroller.ScrollToVerticalOffset(_tapHeight);
    }

    private void ScrollerInput_LostFocus(object sender, RoutedEventArgs e)
    {
      KeyboardPlaceholder.Visibility = Visibility.Collapsed;
    }

    private void ScrollerInput_Tap(object sender, System.Windows.Input.GestureEventArgs e)
    {
      _tapHeight = e.GetPosition(ScrollerInput).Y - 120;
    }
  }
}

Hopefully this template will prove useful in the future.