В Silverlight, как сделать TextBox с IsReadOnly="True"
, не станет серым. Серый эффект выглядит ужасно с моим приложением, и я хотел бы отключить его или изменить его внешний вид/цвет.
Предотвратить выделение текстового поля только для чтения в Silverlight
Ответ 1
В Silverlight 2 есть пара опций, проще всего использовать TextBlock, так как это только когда-либо только на самом деле.
Если вам нужен TextBox, то вам нужно сделать другой стиль, который не влияет на серый цвет.
Чтобы сделать это, откройте смесь. щелкните правой кнопкой мыши на вашем текстовом поле и выберите "Изменить элементы управления" ( "Шаблон" ) → "Редактировать копию"... Назовите новый стиль тем, что вы хотите.
Затем вы хотите отредактировать этот новый стиль и удалить границу с именем "ReadOnlyVisualElement" и удалить раскадровку, которая изменяет свойство непрозрачности этой границы.
Надеюсь, что это поможет.
Добавлен стиль XAML
<Style x:Key="ReadOnlyStyle" TargetType="TextBox">
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Background" Value="#FFFFFFFF"/>
<Setter Property="Foreground" Value="#FF000000"/>
<Setter Property="Padding" Value="2"/>
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFA3AEB9" Offset="0"/>
<GradientStop Color="#FF8399A9" Offset="0.375"/>
<GradientStop Color="#FF718597" Offset="0.375"/>
<GradientStop Color="#FF617584" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid x:Name="RootElement">
<vsm:VisualStateManager.VisualStateGroups>
<vsm:VisualStateGroup x:Name="CommonStates">
<vsm:VisualState x:Name="Normal"/>
<vsm:VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="MouseOverBorder" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)">
<SplineColorKeyFrame KeyTime="0" Value="#FF99C1E2"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</vsm:VisualState>
<vsm:VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="DisabledVisualElement" Storyboard.TargetProperty="Opacity">
<SplineDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</vsm:VisualState>
<vsm:VisualState x:Name="ReadOnly">
<Storyboard>
</Storyboard>
</vsm:VisualState>
</vsm:VisualStateGroup>
<vsm:VisualStateGroup x:Name="FocusStates">
<vsm:VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity">
<SplineDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</vsm:VisualState>
<vsm:VisualState x:Name="Unfocused">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity">
<SplineDoubleKeyFrame KeyTime="0" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</vsm:VisualState>
</vsm:VisualStateGroup>
<vsm:VisualStateGroup x:Name="ValidationStates">
<vsm:VisualState x:Name="Valid"/>
<vsm:VisualState x:Name="InvalidUnfocused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ValidationErrorElement" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</vsm:VisualState>
<vsm:VisualState x:Name="InvalidFocused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ValidationErrorElement" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="validationTooltip" Storyboard.TargetProperty="IsOpen">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<System:Boolean>True</System:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</vsm:VisualState>
</vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>
<Border x:Name="Border" Opacity="1" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="1">
<Grid>
<Border x:Name="MouseOverBorder" BorderBrush="Transparent" BorderThickness="1">
<ScrollViewer x:Name="ContentElement" BorderThickness="0" IsTabStop="False" Padding="{TemplateBinding Padding}"/>
</Border>
</Grid>
</Border>
<Border x:Name="DisabledVisualElement" IsHitTestVisible="False" Opacity="0" Background="#A5F7F7F7" BorderBrush="#A5F7F7F7" BorderThickness="{TemplateBinding BorderThickness}"/>
<Border x:Name="FocusVisualElement" Margin="1" IsHitTestVisible="False" Opacity="0" BorderBrush="#FF6DBDD1" BorderThickness="{TemplateBinding BorderThickness}"/>
<Border x:Name="ValidationErrorElement" Visibility="Collapsed" BorderBrush="#FFDB000C" BorderThickness="1" CornerRadius="1">
<ToolTipService.ToolTip>
<ToolTip x:Name="validationTooltip" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" Template="{StaticResource ValidationToolTipTemplate}" Placement="Right" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}">
<ToolTip.Triggers>
<EventTrigger RoutedEvent="Canvas.Loaded">
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="validationTooltip" Storyboard.TargetProperty="IsHitTestVisible">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<System:Boolean>true</System:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ToolTip.Triggers>
</ToolTip>
</ToolTipService.ToolTip>
<Grid Height="12" HorizontalAlignment="Right" Margin="1,-4,-4,0" VerticalAlignment="Top" Width="12" Background="Transparent">
<Path Fill="#FFDC000C" Margin="1,3,0,0" Data="M 1,0 L6,0 A 2,2 90 0 1 8,2 L8,7 z"/>
<Path Fill="#ffffff" Margin="1,3,0,0" Data="M 0,0 L2,0 L 8,6 L8,8"/>
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Я бы получил предварительный просмотр Blend, кодирование выше вручную было бы большим количеством ненужной работы.
Ответ 2
Кажется, что ничего не работает в xaml (как обычно), поэтому лучшее решение, которое я придумал, - сделать текстовое поле только для чтения без свойства IsReadOnly.
public class ReadOnlyTextBox : TextBox
{
protected override void OnKeyDown(KeyEventArgs e)
{
e.Handled = true;
base.OnKeyDown(e);
}
}
Ответ 3
Если вам нужен только эквивалент блока текста в HTML, который можно выбрать (который по какой-либо причине отсутствует даже в Silverlight 4), вы можете немного сократить ответ Graeme:
<Style x:Key="ReadOnlyStyle" TargetType="TextBox">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Background" Value="#FFFFFFFF"/>
<Setter Property="Padding" Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid x:Name="RootElement">
<vsm:VisualStateManager.VisualStateGroups>
<vsm:VisualStateGroup x:Name="CommonStates">
<vsm:VisualState x:Name="Normal"/>
<vsm:VisualState x:Name="MouseOver"/>
<vsm:VisualState x:Name="Disabled" />
<vsm:VisualState x:Name="ReadOnly"/>
</vsm:VisualStateGroup>
<vsm:VisualStateGroup x:Name="FocusStates">
<vsm:VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity">
<SplineDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</vsm:VisualState>
<vsm:VisualState x:Name="Unfocused">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity">
<SplineDoubleKeyFrame KeyTime="0" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</vsm:VisualState>
</vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>
<Border x:Name="Border" Opacity="1" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="1">
<Grid>
<Border x:Name="MouseOverBorder" BorderBrush="Transparent" BorderThickness="1">
<ScrollViewer x:Name="ContentElement" BorderThickness="0" IsTabStop="False" Padding="{TemplateBinding Padding}"/>
</Border>
</Grid>
</Border>
<Border x:Name="DisabledVisualElement" IsHitTestVisible="False" Opacity="0" Background="#A5F7F7F7" BorderBrush="#A5F7F7F7" BorderThickness="{TemplateBinding BorderThickness}"/>
<Border x:Name="FocusVisualElement" Margin="1" IsHitTestVisible="False" Opacity="0" BorderBrush="#FF6DBDD1" BorderThickness="{TemplateBinding BorderThickness}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Вы даже можете удалить отключенные состояния.
Ответ 4
Здесь расширенная версия ответа @Struan.
Я предполагаю, что вы хотите разрешить Select all
и Copy
, если вы хотите текстовое поле только для чтения. Вам нужно обрабатывать нажатия клавиш, например Ctrl+A
и Ctrl+C
.
Отказ от ответственности: это не полный набор ключей - вам может потребоваться добавить больше, но это позволит скопировать как минимум.
public class ReadOnlyTextBox : TextBox
{
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.Key == Key.Left || e.Key == Key.Right || e.Key == Key.Up || e.Key == Key.Down)
{
base.OnKeyDown(e);
return;
}
if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control ||
(Keyboard.Modifiers & ModifierKeys.Apple) == ModifierKeys.Apple)
{
if (e.Key == Key.A || e.Key == Key.C)
{
// allow select all and copy!
base.OnKeyDown(e);
return;
}
}
e.Handled = true;
base.OnKeyDown(e);
}
}
И вот простой стиль, который я использую, указывает пользователю, что элемент выбирается, но меньше обычного текстового поля.
<Style TargetType="my:ReadOnlyTextBox">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="3,0,3,0"/>
<Setter Property="Background" Value="Transparent"/>
</Style>
Ответ 5
Я нашел решение @Simon_Weaver самым простым в реализации. Единственное изменение, которое я сделал, это проверить Key.Tab вместе с левым/правым/вверх/вниз, чтобы я мог выходить за пределы поля. Я создал класс ReadOnlyTextBox и скопировал код выше. Затем я добавил чек для Key.Tab и скомпилировал. Затем я изменил свой тег Xaml с
<TextBox ... IsEnabled="False" />
к
<MyNameSpace:ReadOnlyTextBox ... Background="LightGray" />
(удаление ссылки IsEnabled и добавление цвета фона). Он выглядит и работает точно так, как я ожидал.
Спасибо Саймону.
Ответ 6
Я хотел уменьшить стиль до голой кости и протестировал его с помощью silverlight 4.0:
<Style x:Key="ReadOnlyStyle" TargetType="TextBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<TextBlock Text="{TemplateBinding Text}" TextAlignment="{TemplateBinding TextAlignment}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Это почти обман, как будто: Hey silverligh, this textbox is a textblock!
Вы должны в конечном итоге добавить что-то в тег TextBlock, чтобы лучше отражать другие свойства TextBox.
Ответ 7
Пока не изменится определение/поведение/появление кнопки, еще одним элегантным решением является простое изменение TextBox на кнопку. Измените свойство "Текст" на свойство "Содержимое", чтобы установить отображаемый текст, удалите настройку "IsReadOnly", и у вас будет тот эффект, который вы хотите, я считаю (плоский текстовый блок, который поддерживает текст и все границы, фон, переднего плана TextBox без изменения непрозрачности [grey-out] и хлопоты определения нового стиля).
Когда пользователь пытается взаимодействовать с этим элементом управления, он имеет изменения в событии клика, но без обработчика событий, связанного с кнопкой, не будет никакого воздействия на ваш интерфейс. Фактически, я думаю, что поведение кнопки по умолчанию заставляет эффект выглядеть как "классный".