2009-06-24 10 views

Respuesta

11

Hay un par de opciones en Silverlight 2, el más simple sería utilizar un TextBlock ya que eso es sólo alguna vez de solo lectura.

Si necesita un TextBox, entonces lo que debe hacer es darle un estilo diferente que no afecte al gris.

Para hacer esto, abra la mezcla. Haga clic derecho en su TextBox y seleccione Editar partes de control (Plantilla) -> Editar una copia ... Llame al nuevo estilo como lo desee.

Luego desea editar este nuevo estilo y eliminar el borde llamado "ReadOnlyVisualElement" y eliminar el guión gráfico que altera la propiedad de opacidad de ese borde.

Espero que esto ayude.

Agregado Estilo 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> 

que tendría la vista previa de la mezcla, la codificación de lo anterior con la mano sería una gran cantidad de trabajo innecesario.

+0

No estoy usando un TextBlock porque todavía quiero poder copiar el texto del cuadro de texto y pegarlo en otro lugar. No tengo Blend (estoy usando Visual Web Developer 2008 Express) por lo que no puedo probar su segunda sugerencia. – Struan

+3

+1 ¡PARA USTED TENGO QUE ENSEÑARME! –

+0

5 años después. sigue siendo útil – Billatron

10

Parece que nada funciona en el xaml (como es habitual), por lo que la mejor solución que he encontrado es crear un cuadro de texto de solo lectura sin la propiedad IsReadOnly.

public class ReadOnlyTextBox : TextBox 
{ 
    protected override void OnKeyDown(KeyEventArgs e) 
    { 
     e.Handled = true; 
     base.OnKeyDown(e); 
    } 
} 
+1

Esto me ayudó con un problema que tenía tratando de hacer un combobox de solo lectura. En mi caso, también tuve que manejar el OnKeyUp con el mismo código para detener el disparo de un controlador de eventos de KeyUp. – voiddog

+0

+1 para 'como siempre' –

+0

Otro +1 para 'como de costumbre'. Un problema con este enfoque es que obtiene el borde y el cursor cuando hace clic en el cuadro de texto. –

2

Aquí hay una versión mejorada de la respuesta de @ Struan.

Supongo que quiere permitir Select all y Copy si quiere un cuadro de texto de solo lectura. Debe manejar las pulsaciones de teclas como Ctrl+A y Ctrl+C.

Descargo de responsabilidad: este no es un juego de llaves completamente completo; puede que necesite agregar más, pero esto permitirá copiar al menos.

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); 
    } 
} 

Y aquí es un estilo sencillo que estoy usando que indica al usuario que el artículo es seleccionable, pero es más pequeño que una caja de texto típico.

<Style TargetType="my:ReadOnlyTextBox"> 
    <Setter Property="BorderThickness" Value="0"/> 
    <Setter Property="Padding" Value="3,0,3,0"/> 
    <Setter Property="Background" Value="Transparent"/> 
</Style> 
+0

hmm backspace todavía funciona :-( – MadSeb

3

Si lo que desea es un equivalente de un bloque de texto en HTML, que puede ser seleccionado (que por alguna razón aún Silverlight 4 no se encuentra) se puede acortar la respuesta de Graeme ligeramente:

<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> 

Incluso puede eliminar los estados deshabilitados.

0

Encontré que la solución de @ Simon_Weaver es la más fácil de implementar. El único cambio que hice fue verificar Key.Tab junto con left/right/up/down para poder salir del campo. Creé la clase ReadOnlyTextBox y copié el código anterior. Luego agregué el cheque para Key.Tab y compilé.A continuación he cambiado de etiqueta Xaml de

<TextBox ... IsEnabled="False" /> 

a

<MyNameSpace:ReadOnlyTextBox ... Background="LightGray" /> 

(eliminando la referencia IsEnabled y añadiendo el color de fondo). Se ve y funciona exactamente como esperaba.

Gracias Simon.

0

que quería reducir el estilo al descubierto el hueso, y probado esto con 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> 

Es casi un tramposo, como decir: Hey silverligh, this textbox is a textblock! Usted debe finalmente añadir algo en la etiqueta TextBlock, a reflejar mejor otras propiedades de TextBox.

0

Hasta que la definición/comportamiento/apariencia de un botón cambie, otra solución más elegante es simplemente cambiar su TextBox a un Botón. Cambie la propiedad 'Texto' a 'Contenido' para configurar el texto, elimine la configuración 'IsReadOnly' y tendrá el efecto que desee, creo (un control plano similar a un cuadro de texto que admite texto y todo el borde, fondo, propiedades en primer plano de un cuadro de texto sin el cambio de opacidad [encajamiento] y la molestia de definir un nuevo estilo).

Cuando un usuario intenta interactuar con este control, sus características cambian en el evento click, pero sin un controlador de eventos asociado con el botón, no habrá ningún impacto en su interfaz. De hecho, creo que el comportamiento del botón predeterminado hace que el efecto parezca algo "genial".

+0

Oh, debo agregar que debe tener cuidado al acceder al control como un componente secundario para asegurarse de que está escribiendo en un botón en lugar de un cuadro de texto, pero supongo que la mayoría los desarrolladores que hacen esta pregunta lo entenderán. – Epsilon3

Cuestiones relacionadas