2014-11-07 3 views
0

Это немного странный вопрос:Visual Studio WPF UI Designer с пользовательских элементов управления

У меня есть пользовательский элемент управления, который наследуется от TextBox, и обеспечивает «призрак» текст - например, он говорит, «Имя пользователя» в коробке пока вы не нажмете внутри него, после чего текст «призрак» исчезнет, ​​и пользователь может ввести их, в данном случае, имя пользователя.

«Призрачный текст» для элемента управления - это просто свойство в подклассе TextBox. Затем я устанавливал для него TextBox.Text.

В окне предварительного просмотра Visual Studio WPAM XAML (стандартный дизайн пользовательского интерфейса) я хотел бы иметь возможность «просматривать» текст «Ghost text» - например, когда вы устанавливаете фактический текст текстового поля, вы можете видеть это в предварительном просмотре, а не только при запуске приложения.

Я попытался установить свойство Text в соответствующий текст Призрака в функции OnInitialised, но это не влияет на предварительный просмотр.

Где я должен помещать код, который влияет на предварительный просмотр элемента управления в дизайнере?

Вопрос с бонусом: есть ли фактическое имя для текстовых полей «призрак»? Было бы хорошо знать будущее!

+1

Это называется ** водяной знак **. [например] (http://mahapps.com/controls/textbox.html) и [этот] (http://social.technet.microsoft.com/wiki/contents/articles/20725.wpf-watermarked-textbox -and-passwordbox.aspx) – MickyD

+0

@ MickyDuncan Ahhhhh, спасибо! – hnefatl

+0

Возможный дубликат [Watermark/hint text/placeholder TextBox в WPF] (http://stackoverflow.com/questions/833943/watermark-hint-text-placeholder-textbox-in-wpf) – MickyD

ответ

2

Есть ли фактическое название для текстовых полей «призрак»? Был бы бог, чтобы знать о будущем!

Я рассматривал это как «намек» при описании его цели или как «водяной знак» при описании его внешнего вида. Я обычно использую первый, поскольку он описывает функцию , что в большей степени соответствует философии дизайна WPF: фактическая презентация определяется шаблоном, а концептуальный «намек» может быть представлен по-разному просто путем применения пользовательского стиль/шаблон. Почему подразумевается, что это должен быть водяной знак, когда кто-то мог бы представить его другим способом?

Дизайн, я думаю, вы приближаетесь к этому неправильно. Я бы реализовал это таким образом, чтобы элементы управления, отличные от TextBox, могли легче выбрать: использовать прикрепленные свойства.

Я хотел бы создать статический класс, скажем HintProperties, который декларирует несколько вложенных свойств зависимостей:

  • Hint - заявляет содержание подсказки; обычно строка, но это не обязательно. Это может быть просто object, сродни Content собственности ContentControl.

  • HasHint - вычисленная только для чтения bool свойство, которое получает перепроверены, когда Hint изменения, а просто указывает на то, имеет ли элемент управления в Hint указано. Полезно как условие Trigger, чтобы переключить видимость указателя подсказки в шаблоне управления.

Затем предоставить собственный стиль для вашего TextBox (или другого элемента управления), который накладывает Hint выступающий на вершину регулярного содержания, скрытого по умолчанию.Добавьте триггер, чтобы уменьшить непрозрачность подсказки, когда элемент управления имеет фокус клавиатуры, а другой - подсказка Visible, когда Text - пустая строка.

Если вы действительно хотите разобраться, вы можете бросить HintTemplate и HintTemplateSelector.


Однако, если это кажется излишним, вы можете просто объявить Hint или Watermark собственность непосредственно на производный TextBox класса. Я бы не попытался реализовать это, условно изменив свойство Text, так как это будет мешать связыванию данных и, возможно, приоритету значений.

+0

Это звучит как более гибкий системы - однако я боюсь, что это значительный перебор для этого проекта (личное использование). Я, вероятно, прибегну к этому, если не найду менее сложное решение, хотя :) – hnefatl

+0

Хорошо, я посмотрю на использование стиля с наложением - это даст мне повод узнать больше о стилях, который я пренебрегал какое-то время! – hnefatl

+0

@hnefatl Согласен с Майком. Посмотрите второй ответ [здесь, на этой странице с колоссальными 230 голосами] (http://stackoverflow.com/questions/833943/watermark-hint-text-placeholder-textbox-in-wpf) для примера кода – MickyD

0

Вы можете сделать это многоразовым способом, используя стиль, который вы обычно заявляете в своем App.xaml. В этом стиле вы заменяете шаблон управления своей собственной реализацией и объединяете некоторые элементы управления. В основном вы составляете WatermarkTextBox от обычного TextBox с прозрачным фоном и размещаете TextBlock элемент управления со стандартным текстом за TextBox. Visibility этого TextBlock привязан к TextBox с использованием определенного TextInputToVisibilityConverter, поэтому он исчезнет, ​​если TextBox имеет текст или просто имеет фокус.

Хотя это, возможно, выглядит как много кода, можно определить один раз и вы можете использовать это везде, где вам нужно, просто установив стиль TextBox

декларации некоторых ресурсов

xmlns:c="clr-namespace:YourNameSpace.Converters" 
<SolidColorBrush x:Key="brushWatermarkBackground" Color="White" /> 
<SolidColorBrush x:Key="brushWatermarkForeground" Color="LightSteelBlue" /> 
<c:TextInputToVisibilityConverter x:Key="TextInputToVisibilityConverter" /> 

декларация стиля:

<Style x:Key="SearchTextBox" TargetType="{x:Type TextBox}"> 
    <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/> 
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/> 
    <Setter Property="AllowDrop" Value="true"/> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type TextBox}"> 
       <Grid Background="{StaticResource brushWatermarkBackground}"> 
        <TextBlock Margin="5,5" Text="Search..." 
         Foreground="{StaticResource brushWatermarkForeground}" > 
         <TextBlock.Visibility> 
          <MultiBinding 
          Converter="{StaticResource TextInputToVisibilityConverter}"> 
          <Binding RelativeSource="{RelativeSource 
           Mode=FindAncestor, AncestorType=TextBox}" 
           Path="Text.IsEmpty" /> 
          <Binding RelativeSource="{RelativeSource 
           Mode=FindAncestor, AncestorType=TextBox}" 
           Path="IsFocused" /> 
          </MultiBinding> 
         </TextBlock.Visibility> 
        </TextBlock> 
        <Border x:Name="Border" Background="Transparent" 
         BorderBrush="{DynamicResource SolidBorderBrush}" 
         BorderThickness="1" Padding="2" CornerRadius="2"> 

         <!-- The implementation places the Content into the 
          ScrollViewer. It must be named PART_ContentHost 
          for the control to function --> 
         <ScrollViewer Margin="0" x:Name="PART_ContentHost" 
          Style="{DynamicResource SimpleScrollViewer}" 
          Background="Transparent"/> 
        </Border> 
       </Grid> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

реализация TextInputToVisibilityConverter, который просто принимает ввод текста, преобразующий в Bool и преобразует его в Visibility. Также учитывает Фокус.

namespace YourNameSpace 
{ 
    public class TextInputToVisibilityConverter : IMultiValueConverter 
    { 
     public object Convert(object[] values, 
       Type targetType, object parameter, 
       System.Globalization.CultureInfo culture) 
     { 
      if (values[0] is bool && values[1] is bool) 
      { 
       bool hasText = !(bool)values[0]; 
       bool hasFocus = (bool)values[1]; 

       if (hasFocus || hasText) 
        return Visibility.Collapsed; 
      } 

      return Visibility.Visible; 
     } 

     public object[] ConvertBack(object value, 
      Type[] targetTypes, object parameter, 
      System.Globalization.CultureInfo culture) 
     { 
      throw new NotImplementedException(); 
     } 
    } 
} 

Теперь вся инфраструктура на месте. В вашем представлении/usercontrol/window просто измените стиль текстового поля, и вот оно, ваше текстовое поле водяного знака.

<TextBox Style="{DynamicResource SearchTextBox}" /> 
Смежные вопросы