2011-12-28 14 views
27

Actualmente, estoy trabajando en un botón personalizado simple que utiliza imágenes suministradas por el usuario como fondo para los estados normal y presionado. Tengo muchos botones, así que decidí escribir un botón personalizado e implementar dos propiedades para las imágenes de los estados presionados y normales.TemplateBinding a DependencyProperty en un control personalizado que no funciona

Aquí está el código que estoy usando

public partial class ThemeableButton : Button 
{ 
    public ThemeableButton() 
    { 
     InitializeComponent(); 
    } 


    public static readonly DependencyProperty PressedContentBackgroundSourceProperty = DependencyProperty.Register(
        "PressedContentBackgroundSource", typeof(ImageSource), typeof(ThemeableButton), null); 
    public ImageSource PressedContentBackgroundSource 
    { 
     get { return (ImageSource)GetValue(PressedContentBackgroundSourceProperty); } 
     set 
     { 
      (value as BitmapImage).CreateOptions = BitmapCreateOptions.BackgroundCreation; 
      SetValue(PressedContentBackgroundSourceProperty, value); 
     } 
    } 


    public static readonly DependencyProperty NormalContentBackgroundSourceProperty = 
     DependencyProperty.Register("NormalContentBackgroundSource", typeof(ImageSource), typeof(ThemeableButton), null); 

    public ImageSource NormalContentBackgroundSource 
    { 
     get { return (ImageSource)GetValue(NormalContentBackgroundSourceProperty); } 
     set 
     { 
      (value as BitmapImage).CreateOptions = BitmapCreateOptions.BackgroundCreation; 
      SetValue(NormalContentBackgroundSourceProperty, value); 
     } 
    } 
} 

escribí el estilo de este botón de la siguiente manera

 <Style x:Key="ThemeableButtonTemplate" TargetType="MJbox_UIComponents_Controls:ThemeableButton"> 
     <Setter Property="Background" Value="Transparent"/> 
     <Setter Property="BorderBrush" Value="{StaticResource PhoneForegroundBrush}"/> 
     <Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/> 
     <Setter Property="BorderThickness" Value="{StaticResource PhoneBorderThickness}"/> 
     <Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiBold}"/> 
     <Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMediumLarge}"/> 
     <Setter Property="Padding" Value="0"/> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="MJbox_UIComponents_Controls:ThemeableButton"> 
        <Grid> 
         <VisualStateManager.VisualStateGroups> 
          <VisualStateGroup x:Name="CommonStates"> 
           <VisualState x:Name="Normal"> 
            <Storyboard> 
             <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Source" Storyboard.TargetName="ButtonBackground"> 
              <DiscreteObjectKeyFrame KeyTime="0" Value="{TemplateBinding NormalContentBackgroundSource}"> 
              </DiscreteObjectKeyFrame> 
             </ObjectAnimationUsingKeyFrames> 
            </Storyboard> 
           </VisualState> 
           <VisualState x:Name="Pressed"> 
            <Storyboard> 
             <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Source" Storyboard.TargetName="ButtonBackground"> 
              <DiscreteObjectKeyFrame KeyTime="0" Value="{TemplateBinding PressedContentBackgroundSource}"> 
              </DiscreteObjectKeyFrame> 
             </ObjectAnimationUsingKeyFrames> 
            </Storyboard> 
           </VisualState> 
          </VisualStateGroup> 
         </VisualStateManager.VisualStateGroups> 
         <Border BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="0"> 
          <Image x:Name="ButtonBackground" Stretch="None" Source="{TemplateBinding NormalContentBackgroundSource}"/> 
         </Border>  
        </Grid> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 

Probé un ejemplo sencillo

<Controls:ThemeableButton Style="{StaticResource ThemeableButtonTemplate}" x:Name="btnDidntNeedIt" NormalContentBackgroundSource="{Binding Source={StaticResource DefaultTheme}, Path=DidntHaveButtonUnselected}" 
            PressedContentBackgroundSource="{Binding Source={StaticResource DefaultTheme}, Path=DidntHaveButtonSelected}" 
     /> 

pero la imagen no se muestra, intenté eliminando TemplateBinding del estilo y lo reemplacé con la fuente relativa a la imagen archivo y funcionó bien. Simplemente no quiero crear un estilo personalizado para cada botón en la aplicación. ¿Alguna solución posible?

Respuesta

71

He encontrado esto antes, TemplateBinding no funciona para las propiedades de dependencia personalizadas en los controles. Ver estas preguntas relacionadas:

issues with template binding and binding of custom component

TemplateBinding does not work in certain cases(when using TranslateTransform)

siempre he utilizado este lugar:

{Binding MyProperty, RelativeSource={RelativeSource TemplatedParent}} 

Es semánticamente lo mismo que TemplateBinding, y también puede apoyar convertidores de valores, etc ..

+0

Gracias Colin, funcionó bien y me salvó los tonos de trabajo – Waleed

+0

Esta es la respuesta que funcionó para mí también. Me gustaría que TemplateBinding simplemente funcionara y que parte del misterio y la arbitrariedad desaparecieran. – TernaryTopiary

+0

"... TemplateBinding no funciona para las propiedades de dependencia personalizadas en los controles [.]" Funciona para mí. '' en el control personalizado 'ControlTemplate' llena el' Rectangle' con mi propiedad de dependencia 'FillBrush', incluso mostrando esa propiedad en la hoja de propiedades de VS y llenándola con lo que configuro a durante el tiempo de diseño. Tal vez eso es algo nuevo desde 2011? De todos modos, funciona bien ahora. (Pero ten cuidado de animar a las cosas que no son 'Freezeable's. Todavía no puedes hacer eso.) –

Cuestiones relacionadas