Гость
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / TextBox, CUE Banner, повторное использование / 20 сообщений из 20, страница 1 из 1
05.07.2016, 13:49
    #39267949
13th
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
TextBox, CUE Banner, повторное использование
Всем привет. Подскажите за такую вещь:

Нужно текстовое поле, в котором нужны водяные знаки (это такая подсказка, которая выводится серым цветом, когда в поле ничего нет, MS называет это CUE Banner). Нашёл несколько реализаций. Самая простая и понятная вот такая:

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
		<TextBox >
			<TextBox.Resources>
				<VisualBrush x:Key="TextBoxCueBannerBrush" TileMode="None" Stretch="None" AlignmentX="Left">
					<VisualBrush.Visual>
						<Grid>
							<TextBlock FontStyle="Italic" Padding="3" Text="Type here e-mail" Foreground="Gray"/>
						</Grid>
					</VisualBrush.Visual>
				</VisualBrush>
			</TextBox.Resources>
			<TextBox.Style>
				<Style TargetType="TextBox">
					<Style.Triggers>
						<Trigger Property="Text" Value="{x:Null}">
							<Setter Property="Background" Value="{StaticResource TextBoxCueBannerBrush}" />
						</Trigger>
						<Trigger Property="Text" Value="">
							<Setter Property="Background" Value="{StaticResource TextBoxCueBannerBrush}" />
						</Trigger>
					</Style.Triggers>
				</Style>
			</TextBox.Style>
		</TextBox>



Этот вариант мне нравится простотой реализации. Но его сложно использовать: строка подсказки и логика её замены зашиты в объекты. Не будешь же писать на каждое текстовое поле по 25 строк XAML-а. А если их на форме десять?

Есть и понавороченней, типа вот такого: http://www.codeproject.com/Articles/101975/Building-a-Search-Text-Box-Control-with-WPF

Использовать - удобно:
Код: xml
1.
<MyControls:MyTextBox CueBanner="Type here e-mail" />


Но геморой - надо делать библиотеку, или подцеплять её к проекту.

Хотелось бы иметь что-то среднее. Подцепил к проекту CS-файл, взял оттуда контрол в одну строку. Или взял стандартный TextBox, и подцепил к нему какой-нибудь стиль. Как бы так сделать?
...
Рейтинг: 0 / 0
05.07.2016, 13:53
    #39267952
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
TextBox, CUE Banner, повторное использование
Что мешает для первого случая вынести браш и стиль в ресурсы и использовать для нужных текстбоксов?

Что мешает сделать свой контрол на базе текстбокса?
...
Рейтинг: 0 / 0
05.07.2016, 14:14
    #39267971
13th
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
TextBox, CUE Banner, повторное использование
Shocker.Pro, текст-то везде разный. Т.о. на каждый текстбокс будет по 2 ресурса. Зачем?
Если бы можно было сделать 10 ресурсов со строками, один параметризированный ресурс браша и один ресурс стиля - было бы отлично. Но как это сделать?
...
Рейтинг: 0 / 0
05.07.2016, 15:32
    #39268064
13th
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
TextBox, CUE Banner, повторное использование
Вот такую конструкцию придумал, но что-то не получается выражение для Binding-а написать:

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
<Window x:Class="TestMarkup.Window2"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window2" Height="148" Width="300" KeyDown="Window_KeyDown">
	<Window.Resources>
		<Style x:Key="TextBoxWithCueBannerStyle" TargetType="TextBox">
			<Style.Resources>
				<VisualBrush x:Key="TextBoxCueBannerBrush" TileMode="None" Stretch="None" AlignmentX="Left">
					<VisualBrush.Visual>
						<TextBlock FontStyle="Italic" Padding="3" Text="{Binding Tag, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=TextBox}}" Foreground="LightGray"/>
					</VisualBrush.Visual>
				</VisualBrush>
			</Style.Resources>
			<Style.Triggers>
				<Trigger Property="Text" Value="{x:Null}">
					<Setter Property="Background" Value="{StaticResource TextBoxCueBannerBrush}" />
				</Trigger>
				<Trigger Property="Text" Value="">
					<Setter Property="Background" Value="{StaticResource TextBoxCueBannerBrush}" />
				</Trigger>
			</Style.Triggers>
		</Style>
	</Window.Resources>
    <StackPanel>
		<TextBox VerticalAlignment="Top" HorizontalAlignment="Stretch" Margin="15" Style="{StaticResource TextBoxWithCueBannerStyle}" Tag="enter e-mail" />
		<Button IsCancel="True" IsDefault="True" Margin="15">Close</Button>

	</StackPanel>
</Window>



Вот такая ошибка:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.TextBox', AncestorLevel='1''. BindingExpression:Path=Tag; DataItem=null; target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
...
Рейтинг: 0 / 0
05.07.2016, 18:35
    #39268235
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
TextBox, CUE Banner, повторное использование
Так, естественно, ничего не выйдет.

Можно просто назначать тестбоксу другой шаблон, состоящий, собственно, из этого же текстбокса и грида с брашем, а привязку текста делать к тому же Tag-у, ну или, скажем к собственному AttachedProperty через TemplatedParent, ну а шаблон разместить в ресурсах.
...
Рейтинг: 0 / 0
05.07.2016, 18:51
    #39268249
Roman Mejtes
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
TextBox, CUE Banner, повторное использование
Shocker.ProТак, естественно, ничего не выйдет.

Можно просто назначать тестбоксу другой шаблон, состоящий, собственно, из этого же текстбокса и грида с брашем, а привязку текста делать к тому же Tag-у, ну или, скажем к собственному AttachedProperty через TemplatedParent, ну а шаблон разместить в ресурсах.
второе будет самым правильным.
Использовать свойство Tag как по мне, не очень правильно и моветон. Одному богу известно, зачем вообще его создали.
...
Рейтинг: 0 / 0
05.07.2016, 18:57
    #39268255
13th
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
TextBox, CUE Banner, повторное использование
Shocker.ProТак, естественно, ничего не выйдет.
Почему?

Shocker.ProМожно просто назначать тестбоксу другой шаблон, состоящий, собственно, из этого же текстбокса и грида с брашем, а привязку текста делать к тому же Tag-у, ну или, скажем к собственному AttachedProperty через TemplatedParent, ну а шаблон разместить в ресурсах.
Пардон, не понял, не можешь пояснить кодом?
...
Рейтинг: 0 / 0
05.07.2016, 18:59
    #39268258
13th
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
TextBox, CUE Banner, повторное использование
Roman MejtesИспользовать свойство Tag как по мне, не очень правильно и моветон. Одному богу известно, зачем вообще его создали.
Тут ты не прав. Иногда надо сделать чтнб, что не помещается в рамки. Свойство Tag часто помогает. Особенно оно годится для новичков, которым некогда разбираться, как сделать что-то заковыристое, а через Tag можно забить гвоздик.
...
Рейтинг: 0 / 0
05.07.2016, 23:14
    #39268376
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
TextBox, CUE Banner, повторное использование
13thможешь пояснить кодом?В принципе - да, свойства браша нельзя прибайндить к свойствам контрола, так как браш не находится в визуальном дереве. Поэтому предлагаю немного другую компоновку
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
  <Window.Resources>
    <ControlTemplate x:Key="cueTemplate" TargetType="TextBox">
      <Grid>
        <Border Padding="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
          <TextBlock FontStyle="Italic" Padding="3" Text="{TemplateBinding Tag}" Foreground="Gray">
            <TextBlock.Style>
              <Style TargetType="TextBlock">
                <Setter Property="Visibility" Value="Collapsed" />
                <Style.Triggers>
                  <DataTrigger Binding="{Binding ElementName=tb, Path=Text}" Value="">
                    <Setter Property="Visibility" Value="Visible" />
                  </DataTrigger>
                  <DataTrigger Binding="{Binding ElementName=tb, Path=Text}" Value="{x:Null}">
                    <Setter Property="Visibility" Value="Visible" />
                  </DataTrigger>
                </Style.Triggers>
              </Style>
            </TextBlock.Style>
          </TextBlock>
        </Border>
        <TextBox x:Name="tb"
                 Text="{TemplateBinding Text}"
                 BorderThickness="{TemplateBinding BorderThickness}"
                 BorderBrush="{TemplateBinding BorderBrush}"
                 Background="Transparent"/>
      </Grid>
    </ControlTemplate>
  </Window.Resources>

  <TextBox Template="{StaticResource cueTemplate}" Tag="bla-bla-bla" />



Причем тут, в отличие от первого примера, возможно настраивать Background для текстбокса.

При необходимости - добавить нужные байндинги для свойств текстбокса, который находится внутри шаблона.
...
Рейтинг: 0 / 0
06.07.2016, 05:32
    #39268433
Roman Mejtes
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
TextBox, CUE Banner, повторное использование
Shocker.Pro13thможешь пояснить кодом?В принципе - да, свойства браша нельзя прибайндить к свойствам контрола, так как браш не находится в визуальном дереве. Поэтому предлагаю немного другую компоновку
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
  <Window.Resources>
    <ControlTemplate x:Key="cueTemplate" TargetType="TextBox">
      <Grid>
        <Border Padding="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
          <TextBlock FontStyle="Italic" Padding="3" Text="{TemplateBinding Tag}" Foreground="Gray">
            <TextBlock.Style>
              <Style TargetType="TextBlock">
                <Setter Property="Visibility" Value="Collapsed" />
                <Style.Triggers>
                  <DataTrigger Binding="{Binding ElementName=tb, Path=Text}" Value="">
                    <Setter Property="Visibility" Value="Visible" />
                  </DataTrigger>
                  <DataTrigger Binding="{Binding ElementName=tb, Path=Text}" Value="{x:Null}">
                    <Setter Property="Visibility" Value="Visible" />
                  </DataTrigger>
                </Style.Triggers>
              </Style>
            </TextBlock.Style>
          </TextBlock>
        </Border>
        <TextBox x:Name="tb"
                 Text="{TemplateBinding Text}"
                 BorderThickness="{TemplateBinding BorderThickness}"
                 BorderBrush="{TemplateBinding BorderBrush}"
                 Background="Transparent"/>
      </Grid>
    </ControlTemplate>
  </Window.Resources>

  <TextBox Template="{StaticResource cueTemplate}" Tag="bla-bla-bla" />



Причем тут, в отличие от первого примера, возможно настраивать Background для текстбокса.

При необходимости - добавить нужные байндинги для свойств текстбокса, который находится внутри шаблона.

не хочу ни кого обижать, но это хрень, а не шаблон для TextBox'а, у вас получается замкнутый круг, TextBox В TextBox'е.
вообще TextBox в своём роде уникальный контрол, уникален он тем, что в шаблоне его внутренняя часть ни как не декларирована, вместо этого, берёт TemplatePart этого шаблона, он имеет тип ScrollViewer и имя PART_ContentHost, он является неотъемлемой частью шаблона.
простейший шаблон TextBox'а выглядит след. образом:
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
<ControlTemplate x:Key="cueTemplate" TargetType="{x:Type TextBox}">
	<Border Padding="{TemplateBinding BorderThickness}" 
			Background="{TemplateBinding Background}"
			BorderBrush="{TemplateBinding BorderBrush}"
			BorderThickness="{TemplateBinding BorderThickness}">
			<ScrollViewer x:Name="PART_ContentHost" />
	</Border>
</ControlTemplate>


когда у экземпляра TextBox, будет вызван метод ApplyTemplate(), в методы осуществляется поиск элемента шаблона PART_ContentHost, и в коде задается его содержимое.

Кстати, с куем есть еще 1 вариант, на подбие работы фокуса и валидации, можно поверх любого котрола размещать адорнен.
+ этого метода в том, что нам не надо менять шаблон элементов управления вообще, такой способ будет работать со всеми контролами без исключения (с ComboBox'ами, к примеру) и будет максимально универсальный.

В качестве свойства с контентов куя лучше использовать не string, а object, а для представления в UI, не TextBlock, а ContentPresenter.
Это даст более широкие возможности для управления содержимым куя. Если в свойстве будет строка, то ContentPresenter отобразит её как TextBlock (или AccessText), если содержимое будет UIElement, то оно отобразится как есть. Аналогичным образом работает ToolTip.
...
Рейтинг: 0 / 0
06.07.2016, 09:12
    #39268487
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
TextBox, CUE Banner, повторное использование
Roman Mejtesу вас получается замкнутый круг, TextBox В TextBox'еТак я и хочу сохранить текстбокс как текстбокс. С нужным поведением и визуализацией. В частности, текстбокс поддерживает темы виндов - переключи-ка на "классическую" - мой вариант классическим станет, твой - нет. То есть я просто взял текстбокс и добавил к нему надпись. Можно было сделать и на адорнере, но это - рабочий вариант "на коленке" на базе примера ТС.
...
Рейтинг: 0 / 0
06.07.2016, 10:13
    #39268536
Roman Mejtes
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
TextBox, CUE Banner, повторное использование
Shocker.ProRoman Mejtesу вас получается замкнутый круг, TextBox В TextBox'еТак я и хочу сохранить текстбокс как текстбокс. С нужным поведением и визуализацией. В частности, текстбокс поддерживает темы виндов - переключи-ка на "классическую" - мой вариант классическим станет, твой - нет. То есть я просто взял текстбокс и добавил к нему надпись. Можно было сделать и на адорнере, но это - рабочий вариант "на коленке" на базе примера ТС.не использую стандартные шаблоны контролов, WPF для чего существует? чтоб всё было стандартным? :)
...
Рейтинг: 0 / 0
06.07.2016, 10:55
    #39268565
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
TextBox, CUE Banner, повторное использование
Roman Mejtesне использую стандартные шаблоны контролов, WPF для чего существует? чтоб всё было стандартным? :)Ну если ты не используешь - это ж не значит, что другие не используют? ))
...
Рейтинг: 0 / 0
06.07.2016, 16:15
    #39269068
13th
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
TextBox, CUE Banner, повторное использование
Похоже, с водяными знаками всё плохо. Придётся отдельный контрол написать, и его использовать, а не хотелось.
...
Рейтинг: 0 / 0
06.07.2016, 16:32
    #39269092
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
TextBox, CUE Banner, повторное использование
13thвсё плохоа чем не понравился мой вариант?
...
Рейтинг: 0 / 0
06.07.2016, 18:27
    #39269200
13th
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
TextBox, CUE Banner, повторное использование
Shocker.Pro, во-первых, внешний контрол по размерам не совпадает с тем, что накрывается. Во-вторых, у меня не получилось спрятать его во время фокуса.
...
Рейтинг: 0 / 0
06.07.2016, 18:31
    #39269203
13th
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
TextBox, CUE Banner, повторное использование
Roman Mejtes, У меня 500 edito-ов, написанных на ATL, я сейчас добавлю ещё дюжину, и хотелось бы, что бы они были похожими на предыдущие.

Кстати, выдел пример с универсальным адорнером, но блин, сколько же гемора из-за пяти-шести водяных знаков! Право же, лучше скопипастить сотню строк XAML-а.
...
Рейтинг: 0 / 0
06.07.2016, 18:43
    #39269212
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
TextBox, CUE Banner, повторное использование
13thShocker.Pro, во-первых, внешний контрол по размерам не совпадает с тем, что накрывается. Во-вторых, у меня не получилось спрятать его во время фокуса.Ну, ёмаё, вы ж не просили законченное решение.
По поводу фокуса - добавляете еще один триггер в конце и вуаля.
Код: xml
1.
2.
3.
                  <DataTrigger Binding="{Binding ElementName=tb, Path=IsFocused}" Value="True">
                    <Setter Property="Visibility" Value="Collapsed" />
                  </DataTrigger>

По поводу размеров не очень понятна проблема, но, полагаю, все тоже легко решаемо
...
Рейтинг: 0 / 0
07.07.2016, 13:28
    #39269733
13th
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
TextBox, CUE Banner, повторное использование
Shocker.Pro, спасибо за подсказку с фокусом. Я чуть позже попробую, напишу, что получилось.
...
Рейтинг: 0 / 0
12.07.2016, 16:08
    #39272518
13th
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
TextBox, CUE Banner, повторное использование
Закончилось всё тем, чем и должно было закончиться: заюзал WPF ToolKit. Всем спасибо за помощь (^:
...
Рейтинг: 0 / 0
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / TextBox, CUE Banner, повторное использование / 20 сообщений из 20, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]