Search code examples
c#xamarin.formsuwpxamarin.uwp

How to use a Custom Renderer for my Entry Controls


I am trying to change a Xamarin Forms (UWP) Entry Control's Vertical Centering based on this Answer.

I changed my App.xaml (In the UWP project) to:

<Application
    x:Class="Prism.PointOfSale.UWP.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Prism.PointOfSale.UWP"
    RequestedTheme="Light">

    <Application.Resources>
        <Style x:Key="TextBoxStyle1" TargetType="TextBox">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="TextBox">
                        <Grid>
                            <Border x:Name="BorderElement" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" Grid.ColumnSpan="2" Grid.RowSpan="1" Grid.Row="1"/>
                            <ContentPresenter  x:Name="HeaderContentPresenter" VerticalAlignment="Center"  ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" Grid.ColumnSpan="2" FontWeight="Normal" Foreground="{ThemeResource TextControlHeaderForeground}" Margin="0,0,0,8" Grid.Row="0" TextWrapping="{TemplateBinding TextWrapping}" Visibility="Collapsed" x:DeferLoadStrategy="Lazy"/>
                            <ScrollViewer x:Name="ContentElement" VerticalAlignment="Center" AutomationProperties.AccessibilityView="Raw" HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}" IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}" IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}" IsTabStop="False" IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}" Margin="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" Grid.Row="1" VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}" VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}" ZoomMode="Disabled"/>
                            <TextBlock x:Name="PlaceholderTextContentPresenter" Grid.ColumnSpan="2" Foreground="{Binding PlaceholderForeground, RelativeSource={RelativeSource Mode=TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForeground}}" IsHitTestVisible="False" Margin="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" Grid.Row="1" Text="{TemplateBinding PlaceholderText}" TextWrapping="{TemplateBinding TextWrapping}" TextAlignment="{TemplateBinding TextAlignment}"/>
                            <Button x:Name="DeleteButton" AutomationProperties.AccessibilityView="Raw" BorderThickness="{TemplateBinding BorderThickness}" Grid.Column="1" FontSize="{TemplateBinding FontSize}" IsTabStop="False" MinWidth="34" Margin="{ThemeResource HelperButtonThemePadding}" Grid.Row="1" Style="{StaticResource DeleteButtonStyle}" VerticalAlignment="Stretch" Visibility="Collapsed"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Application.Resources>
</Application>

I added this Renderer to the UWP Project:

[assembly: ExportRenderer(typeof(Entry), typeof(CustomTextBoxRenderer))]
namespace Prism.PointOfSale.UWP
{
    public class CustomTextBoxRenderer : EntryRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);

            if (this.Control != null)
            {
                this.Control.Height = 60;
                Control.Style = (Windows.UI.Xaml.Style)App.Current.Resources["TextBoxStyle1"];
            }
        }
    }
}

The Build locked up for about 2 minutes. But, my text is still on the bottom of the Entry Control after the form loaded. What else do I need to do to use the custom renderer?


Solution

  • The Build locked up for about 2 minutes. But, my text is still on the bottom of the Entry Control after the form loaded.

    The problem is your TextBoxStyle1 is not complete, please copy the following style to replace, and set ContentElement scrollviewer VerticalAlignment as Center.

    <Style x:Key="TextBoxStyle1" TargetType="TextBox">
        <Setter Property="Foreground" Value="{ThemeResource TextControlForeground}" />
        <Setter Property="Background" Value="{ThemeResource TextControlBackground}" />
        <Setter Property="BorderBrush" Value="{ThemeResource TextControlBorderBrush}" />
        <Setter Property="SelectionHighlightColor" Value="{ThemeResource TextControlSelectionHighlightColor}" />
        <Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
        <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
        <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
        <Setter Property="ScrollViewer.HorizontalScrollMode" Value="Auto" />
        <Setter Property="ScrollViewer.VerticalScrollMode" Value="Auto" />
        <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
        <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden" />
        <Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
        <Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}" />
        <Setter Property="UseSystemFocusVisuals" Value="{ThemeResource IsApplicationFocusVisualKindReveal}" />
        <Setter Property="ContextFlyout" Value="{StaticResource TextControlCommandBarContextFlyout}" />
        <Setter Property="SelectionFlyout" Value="{StaticResource TextControlCommandBarSelectionFlyout}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="TextBox">
                    <Grid>
                        <Grid.Resources>
                            <Style x:Name="DeleteButtonStyle" TargetType="Button">
                                <Setter Property="Template">
                                    <Setter.Value>
                                        <ControlTemplate TargetType="Button">
                                            <Grid
                                                x:Name="ButtonLayoutGrid"
                                                Background="{ThemeResource TextControlButtonBackground}"
                                                BorderBrush="{ThemeResource TextControlButtonBorderBrush}"
                                                BorderThickness="{TemplateBinding BorderThickness}">
                                                <TextBlock
                                                    x:Name="GlyphElement"
                                                    HorizontalAlignment="Center"
                                                    VerticalAlignment="Center"
                                                    AutomationProperties.AccessibilityView="Raw"
                                                    FontFamily="{ThemeResource SymbolThemeFontFamily}"
                                                    FontSize="12"
                                                    FontStyle="Normal"
                                                    Foreground="{ThemeResource TextControlButtonForeground}"
                                                    Text="&#xE10A;" />
    
                                                <VisualStateManager.VisualStateGroups>
                                                            <VisualStateGroup x:Name="CommonStates">
                                                                <VisualState x:Name="Normal" />
    
                                                                <VisualState x:Name="PointerOver">
                                                                    <Storyboard>
                                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="Background">
                                                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBackgroundPointerOver}" />
                                                                        </ObjectAnimationUsingKeyFrames>
                                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="BorderBrush">
                                                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBorderBrushPointerOver}" />
                                                                        </ObjectAnimationUsingKeyFrames>
                                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement" Storyboard.TargetProperty="Foreground">
                                                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonForegroundPointerOver}" />
                                                                        </ObjectAnimationUsingKeyFrames>
                                                                    </Storyboard>
                                                                </VisualState>
    
                                                                <VisualState x:Name="Pressed">
                                                                    <Storyboard>
                                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="Background">
                                                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBackgroundPressed}" />
                                                                        </ObjectAnimationUsingKeyFrames>
                                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="BorderBrush">
                                                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBorderBrushPressed}" />
                                                                        </ObjectAnimationUsingKeyFrames>
                                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement" Storyboard.TargetProperty="Foreground">
                                                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonForegroundPressed}" />
                                                                        </ObjectAnimationUsingKeyFrames>
                                                                    </Storyboard>
                                                                </VisualState>
    
                                                                <VisualState x:Name="Disabled">
                                                                    <Storyboard>
                                                                        <DoubleAnimation
                                                                            Storyboard.TargetName="ButtonLayoutGrid"
                                                                            Storyboard.TargetProperty="Opacity"
                                                                            To="0"
                                                                            Duration="0" />
                                                                    </Storyboard>
                                                                </VisualState>
                                                            </VisualStateGroup>
                                                        </VisualStateManager.VisualStateGroups>
                                            </Grid>
                                        </ControlTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </Grid.Resources>
    
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="*" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
    
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>
    
                        <ContentPresenter
                            x:Name="HeaderContentPresenter"
                            Grid.Row="0"
                            Grid.Column="0"
                            Grid.ColumnSpan="2"
                            Margin="{ThemeResource TextBoxTopHeaderMargin}"
                            VerticalAlignment="Top"
                            x:DeferLoadStrategy="Lazy"
                            Content="{TemplateBinding Header}"
                            ContentTemplate="{TemplateBinding HeaderTemplate}"
                            FontWeight="Normal"
                            Foreground="{ThemeResource TextControlHeaderForeground}"
                            TextWrapping="Wrap"
                            Visibility="Collapsed" />
                        <Border
                            x:Name="BorderElement"
                            Grid.Row="1"
                            Grid.RowSpan="1"
                            Grid.Column="0"
                            Grid.ColumnSpan="2"
                            MinWidth="{ThemeResource TextControlThemeMinWidth}"
                            MinHeight="{ThemeResource TextControlThemeMinHeight}"
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Control.IsTemplateFocusTarget="True"
                            CornerRadius="{TemplateBinding CornerRadius}" />
                        <ScrollViewer
                            x:Name="ContentElement"
                            Grid.Row="1"
                            Grid.Column="0"
                            Margin="{TemplateBinding BorderThickness}"
                            Padding="{TemplateBinding Padding}"
                            VerticalAlignment="Center"
                            AutomationProperties.AccessibilityView="Raw"
                            HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
                            HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
                            IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
                            IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
                            IsTabStop="False"
                            IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
                            VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
                            VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
                            ZoomMode="Disabled" />
                        <TextBlock
                            x:Name="PlaceholderTextContentPresenter"
                            Grid.Row="1"
                            Grid.Column="0"
                            Grid.ColumnSpan="2"
                            Margin="{TemplateBinding BorderThickness}"
                            Padding="{TemplateBinding Padding}"
                            Foreground="{Binding PlaceholderForeground, RelativeSource={RelativeSource TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForeground}}"
                            IsHitTestVisible="False"
                            Text="{TemplateBinding PlaceholderText}"
                            TextAlignment="{TemplateBinding TextAlignment}"
                            TextWrapping="{TemplateBinding TextWrapping}" />
                        <Button
                            x:Name="DeleteButton"
                            Grid.Row="1"
                            Grid.Column="1"
                            MinWidth="34"
                            Margin="{ThemeResource HelperButtonThemePadding}"
                            VerticalAlignment="Stretch"
                            AutomationProperties.AccessibilityView="Raw"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            FontSize="{TemplateBinding FontSize}"
                            IsTabStop="False"
                            Style="{StaticResource DeleteButtonStyle}"
                            Visibility="Collapsed" />
                        <ContentPresenter
                            x:Name="DescriptionPresenter"
                            Grid.Row="2"
                            Grid.Column="0"
                            Grid.ColumnSpan="2"
                            x:Load="False"
                            AutomationProperties.AccessibilityView="Raw"
                            Content="{TemplateBinding Description}"
                            Foreground="{ThemeResource SystemControlDescriptionTextForegroundBrush}" />
    
                        <VisualStateManager.VisualStateGroups>
                                    <VisualStateGroup x:Name="CommonStates">
                                        <VisualState x:Name="Normal" />
    
                                        <VisualState x:Name="Disabled">
    
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderContentPresenter" Storyboard.TargetProperty="Foreground">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlHeaderForegroundDisabled}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundDisabled}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushDisabled}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundDisabled}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding PlaceholderForeground, RelativeSource={RelativeSource TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForegroundDisabled}}" />
                                                </ObjectAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </VisualState>
    
                                        <VisualState x:Name="PointerOver">
    
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushPointerOver}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundPointerOver}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding PlaceholderForeground, RelativeSource={RelativeSource TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForegroundPointerOver}}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundPointerOver}" />
                                                </ObjectAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </VisualState>
                                        <VisualState x:Name="Focused">
    
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding PlaceholderForeground, RelativeSource={RelativeSource TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForegroundFocused}}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundFocused}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushFocused}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundFocused}" />
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="RequestedTheme">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="Light" />
                                                </ObjectAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </VisualState>
    
                                    </VisualStateGroup>
                                    <VisualStateGroup x:Name="ButtonStates">
                                        <VisualState x:Name="ButtonVisible">
    
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="DeleteButton" Storyboard.TargetProperty="Visibility">
                                                    <DiscreteObjectKeyFrame KeyTime="0">
                                                        <DiscreteObjectKeyFrame.Value>
                                                            <Visibility>Visible</Visibility>
                                                        </DiscreteObjectKeyFrame.Value>
                                                    </DiscreteObjectKeyFrame>
                                                </ObjectAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </VisualState>
                                        <VisualState x:Name="ButtonCollapsed" />
    
                                    </VisualStateGroup>
    
                                </VisualStateManager.VisualStateGroups>
                    </Grid>
    
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>