2009-10-07 39 views
8

Quiero personalizar el estado de alternar del botón de alternar en wpf. Quiero establecer una imagen para el botón de alternar cuando está activado y configurar otra imagen cuando está desactivado. PARA HACERLO, pensé en usar disparadores. Esta es la forma en que terminé haciendo,Personalizar el estado de alternar de un botón de alternar en wpf

<Window ...> 
    <Window.Resources> 
     <Image x:Key="OnImage" Source="C:\ON.jpg" /> 
     <Image x:Key="OffImage" Source="C:\OFF.jpg" /> 
     <Style x:Key="OnOffToggleImageStyle" TargetType="ToggleButton"> 
      <Style.Triggers> 
       <Trigger Property="IsChecked" Value="True"> 
        <Setter Property="Content" Value="{StaticResource OnImage}" /> 
       </Trigger> 
       <Trigger Property="IsChecked" Value="False"> 
        <Setter Property="Content" Value="{StaticResource OffImage}" /> 
       </Trigger> 
      </Style.Triggers> 
     </Style> 
    </Window.Resources> 
    <ListBox> 
     <ListBox.ItemTemplate> 
      <DataTemplate> 
       ... 
       <ToggleButton IsChecked="{Binding Status}" Width="100" Height="35" Style="{StaticResource OnOffToggleImageStyle}" /> 
       ... 
      </DataTemplate> 
     </ListBox.ItemTemplate> 
</Window> 

El fragmento anterior parece funciona bien sólo para los dos elementos del cuadro de lista. Si más de un elemento tiene el valor de enlace, el estado es verdadero, no funciona (funciona solo para uno de dichos elementos). Por favor dígame si estoy yendo en la dirección correcta. También dime otras formas de lograr esto.

Respuesta

10

El problema aquí es porque está utilizando Image recursos. El Image en sus recursos es una instancia concreta de un control. Solo puede estar en un lugar a la vez. Así que cuando usted tiene más de un elemento de la lista ...

Esto debería funcionar para usted:

<Style x:Key="OnOffToggleImageStyle" TargetType="ToggleButton"> 
<Style.Triggers> 
    <Trigger Property="IsChecked" Value="True"> 
    <Setter Property="Content"> 
     <Setter.Value> 
     <Image Source="C:\ON.jpg" /> 
     </Setter.Value> 
    </Setter> 
    </Trigger> 
    <Trigger Property="IsChecked" Value="False"> 
    <Setter Property="Content"> 
     <Setter.Value> 
     <Image Source="C:\OFF.jpg" /> 
     </Setter.Value> 
    </Setter> 
    </Trigger> 
</Style.Triggers> 
</Style> 

Observe que puede mejorar el rendimiento de esto mediante el uso de un ImageSource para cada archivo de imagen en su recursos, luego haciendo referencia a esto en el Image. Esto significa que cada imagen solo se carga una vez desde el disco, en lugar de 2 * N veces (donde N es el número de elementos en su lista).

+3

El fragmento anterior es una excepción. Aquí están los detalles, No se puede agregar el contenido del tipo 'System.Windows.Controls.Image' a un objeto de tipo 'System.Object'. Error en el objeto 'System.Windows.Controls.Image' en el archivo de marcado – sudarsanyes

+1

Esto fue muy útil. :) Gracias .. –

5

This answer le ayudará. Allí tomé un ToggleButton y lo diseñé para que se vea como el ToggleButton en una TreeView (la parte +/- para expandir los nodos de colapso). Solo tendrá que cambiar las rutas que dibujan los signos - y +, para mostrar sus imágenes en su lugar.

Aquí va personalizado, simplemente ponga una imagen llamada "on.jpg" y otra llamada "off.jpg" en su directorio C: \, y debería funcionar simplemente copiando/pegando en su ventana:

<Window.Resources> 
     <SolidColorBrush x:Key="GlyphBrush" Color="#444" /> 
     <ControlTemplate x:Key="toggleButtonTemplate" TargetType="ToggleButton"> 
      <Grid 
       Width="15" 
       Height="13" 
       Background="Transparent"> 
       <Image x:Name="ExpandImage" 
         Source="C:\off.jpg" 
         HorizontalAlignment="Left" 
         VerticalAlignment="Center" 
         Margin="1,1,1,1" />      
      </Grid> 
      <ControlTemplate.Triggers> 
       <Trigger Property="IsChecked" 
        Value="True"> 
        <Setter Property="Source" 
         TargetName="ExpandImage" 
         Value="C:\on.jpg"/> 
       </Trigger> 
      </ControlTemplate.Triggers> 
     </ControlTemplate> 
     <Style x:Key="toggleButtonStyle" TargetType="ToggleButton"> 
      <Setter Property="Template" Value="{StaticResource toggleButtonTemplate}" /> 
     </Style> 
    </Window.Resources> 
    <Grid> 
     <ToggleButton Style="{StaticResource toggleButtonStyle}" /> 
    </Grid> 
+0

¿Qué es ExpandImage en el fragmento de arriba? No hay tipos de disparadores llamados ExpandImage. ¿Podrías echarle un vistazo? – sudarsanyes

+0

El nombre de la imagen dentro de su plantilla: . Esto es para que ControlTemplate pueda acceder a él y modificar sus propiedades: Carlo

+0

Lo siento, no lo leí completamente. Gracias. Está funcionando ahora. ¿Por qué no estaba funcionando para mí? ¿Por qué solo venía una vez? – sudarsanyes

1

Me gusta Drew Noakes dijo: en mi snippte solo había dos imágenes. Así que solo dos elementos funcionaban correctamente. Resolví este problema con el siguiente fragmento.

<ToggleButton 
    Grid.Row="0" Grid.Column="2" Grid.RowSpan="2" 
    VerticalAlignment="Center" HorizontalAlignment="Center" 
    IsChecked="{Binding Status}" 
    Width="100" Height="35"> 
    <ToggleButton.Resources> 
    <Image x:Key="OnImage" Source="C:\ON.jpg" /> 
    <Image x:Key="OffImage" Source="C:\OFF.jpg" /> 
    </ToggleButton.Resources> 
    <ToggleButton.Style> 
    <Style TargetType="ToggleButton"> 
     <Style.Triggers> 
     <Trigger Property="IsChecked" Value="True"> 
      <Setter Property="Content" Value="{StaticResource OnImage}"> 
      </Setter> 
     </Trigger> 
     <Trigger Property="IsChecked" Value="False"> 
      <Setter Property="Content" Value="{StaticResource OffImage}"> 
      </Setter> 
     </Trigger> 
     </Style.Triggers> 
    </Style> 
    </ToggleButton.Style> 
</ToggleButton> 

Simple, moví los desencadenantes a la plantilla de datos. No sé si esta es la respuesta correcta tú. Parece estar funcionando

+0

Interesante, obtengo el error 'System.Windows.Controls.Image' no es un valor válido para 'Setter.Value'; los valores derivados de Visual o ContentElement no son compatibles. –

+0

Gracias por publicar esta respuesta. – Tony

3

Aquí es un ToggleButton con 3 imágenes y un mensaje emergente:

  1. Una imagen para cuando IsChecked = false.
  2. Una imagen para cuando IsChecked = true.
  3. Una imagen para cuando IsMouseOver = true.

Las imágenes se almacenan en recursos como BitmapImage para evitar el cambio de visuales en trigers.

Los archivos de imagen deben agregarse a recursos y luego, los archivos agregados a la carpeta "Resoruces" en el proyecto deben marcarse como BuildAction = Resource.

También aplica una opacidad al control de imagen cuando ToggleButton IsEnabled = false;

Código:

<ToggleButton 
     x:Name="btnToggleImage" 
     Margin="5" 
     Width="50"    
     Height="50" 
     > 
     <ToggleButton.Resources> 
      <BitmapImage x:Key="imgNormal" UriSource="/YOURPROJECTNAME;component/Resources/YourUncheckedImage.png"/> 
      <BitmapImage x:Key="imgHover" UriSource="/YOURPROJECTNAME;component/Resources/YourHoverImage.png"/> 
      <BitmapImage x:Key="imgChecked" UriSource="/YOURPROJECTNAME;component/Resources/YourCheckedImage.png"/> 
     </ToggleButton.Resources> 

     <ToggleButton.Style> 
      <Style TargetType="ToggleButton"> 
       <Setter Property="Template"> 
        <Setter.Value> 
         <ControlTemplate TargetType="ToggleButton"> 
          <Image 
           x:Name="PART_Image" 
           Source="{StaticResource imgNormal}" 
           /> 
          <ControlTemplate.Triggers> 
           <Trigger Property="IsChecked" Value="true"> 
            <Setter TargetName="PART_Image" Property="Source" Value="{StaticResource imgChecked}"/> 
           </Trigger> 
           <Trigger Property="IsMouseOver" Value="true"> 
            <Setter TargetName="PART_Image" Property="Source" Value="{StaticResource imgHover}"/> 
           </Trigger> 
           <Trigger Property="IsEnabled" Value="false"> 
            <Setter TargetName="PART_Image" Property="Opacity" Value="0.6"/> 
           </Trigger> 
          </ControlTemplate.Triggers> 
         </ControlTemplate> 
        </Setter.Value> 
       </Setter> 
      </Style> 
     </ToggleButton.Style> 
    </ToggleButton>   

    <Popup 
     x:Name="popup1" 
     PlacementTarget="{Binding ElementName=btnToggleImage}" 
     PopupAnimation="Slide" 
     IsOpen="{Binding ElementName=btnToggleImage, Path=IsChecked, Mode=TwoWay}" 
     StaysOpen="False" 
     MinWidth="{Binding ElementName=btnToggleImage, Path=Width}"> 
     <Grid Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"> 
      <!--<ItemsPresenter/>--> 
      <Label Content="Hello Wolrd!"/> 
     </Grid> 
    </Popup>