2013-11-29 3 views
1

Мне нужно создать пользовательский TextBox в WPF, и текстовое поле будет иметь некоторую цифру и строку «% Per Annum», например «55% в год». Пользователь должен иметь возможность изменять только цифру из текстового поля, я хочу сохранить строку «% Per Annum» как uneditable. Пожалуйста, помогите мне.Пользовательский текстовый блок с частью фиксированного контента

+1

Это звучит довольно нестандартный пользовательский интерфейс и, следовательно, (относительно) дорогой. Нет ли способа, чтобы устройство могло жить вне текстового поля более стандартно? –

ответ

1

В WPF вы можете изменить шаблон элемента управления, чтобы полностью изменить внешний вид при сохранении функциональности. В вашем случае вы можете изменить шаблон управления TextBox, добавив дополнительный текст внутри границы элемента управления.

В Visual Studio добавьте TextBox к вашему XAML. Затем в Оформить заказ можно правой кнопкой мыши по кнопке TextBox и выберите Редактировать шаблон =>Редактировать копию .... A Style для TextBox затем добавляется в ваш XAML, включая копию ControlTemplate, используемую по умолчанию TextBox. Затем вы можете изменить шаблон по своему усмотрению.

Основная часть TextBox - это ScrollViewer внутри границы ListBoxChrome. Чтобы получить желаемый результат, вы можете обернуть ScrollViewer внутри Grid двумя столбцами, а затем поместить TextBlock с текстом «% per Annum» во втором столбце. Возможно, вы также захотите правильно выровнять текст в TextBox, и вы можете сделать это по умолчанию, установив HorizontalContentAlignment в Right в StyleTextBox.

Вот полный пример XAML, где я добавил некоторые комментарии, чтобы показать, где я сделал изменения:

<Window 
    x:Class="WpfApplication.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" 
    Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
    <LinearGradientBrush x:Key="TextBoxBorder" EndPoint="0,20" MappingMode="Absolute" StartPoint="0,0"> 
     <GradientStop Color="#ABADB3" Offset="0.05"/> 
     <GradientStop Color="#E2E3EA" Offset="0.07"/> 
     <GradientStop Color="#E3E9EF" Offset="1"/> 
    </LinearGradientBrush> 
    <Style x:Key="PerAnnumTextBoxStyle" BasedOn="{x:Null}" TargetType="{x:Type TextBox}"> 
     <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> 
     <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/> 
     <Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/> 
     <Setter Property="BorderThickness" Value="1"/> 
     <Setter Property="Padding" Value="1"/> 
     <Setter Property="AllowDrop" Value="true"/> 
     <Setter Property="FocusVisualStyle" Value="{x:Null}"/> 
     <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/> 
     <Setter Property="Stylus.IsFlicksEnabled" Value="False"/> 
     <!-- New setter --> 
     <Setter Property="HorizontalContentAlignment" Value="Right"/> 
     <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type TextBox}"> 
      <Themes:ListBoxChrome x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" SnapsToDevicePixels="true"> 
       <!-- ScrollViewer wrapped in a Grid --> 
       <Grid> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition/> 
        <ColumnDefinition Width="Auto"/> 
       </Grid.ColumnDefinitions> 
       <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
       <TextBlock Grid.Column="1" Margin="0,1"> % Per Annum</TextBlock> 
       </Grid> 
      </Themes:ListBoxChrome> 
      <ControlTemplate.Triggers> 
       <Trigger Property="IsEnabled" Value="false"> 
       <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/> 
       <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> 
       </Trigger> 
      </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
     </Setter> 
     <Style.Triggers> 
     <MultiTrigger> 
      <MultiTrigger.Conditions> 
      <Condition Property="IsInactiveSelectionHighlightEnabled" Value="true"/> 
      <Condition Property="IsSelectionActive" Value="false"/> 
      </MultiTrigger.Conditions> 
      <Setter Property="SelectionBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/> 
     </MultiTrigger> 
     </Style.Triggers> 
    </Style> 
    </Window.Resources> 
    <StackPanel> 
    <TextBox Text="50" Style="{StaticResource PerAnnumTextBoxStyle}" Width="100" HorizontalAlignment="Left"/> 
    </StackPanel> 
</Window> 
0

Самым простым и в моем opionion лучший способ это поставить текстовое поле внутри StackPanel

<StackPanel Orientation="Horizontal"> 
    <TextBox Text="{Binding Path=MyTextProperty}"/> 
    <Label Content="55% Per Annum" /> 
</StackPanel> 
Смежные вопросы