views:

200

answers:

2

Hi there,

What is the easiest way to create a Silverlight Button with custom Content which knows how to 'look' disabled? I.e. if you set IsEnabled="False" it will look greyed out.

The custom Content will be dead simple, text and an image.

I have done this before in a WPF application quite easily by setting the Content to a StackPanel containing a TextBlock and an Image. I then implemented a Style Trigger on the Image to change it to a greyed out version when it wasn't enabled. The text changed colour by itself.

As far as I can tell the custom Content disappears altogether when the button is disabled in Silverlight.

Any help is appreciated.

Cheers, Andrej.

+2  A: 

Assuming you haven't changed the Button's template, the default control template for Button uses the VisualStateManager to overlay a white rectangle with 50% transparency over whatever content you have in the button. This should give the content a "washed out" look.

If you have replaced the template, you would need to replicate this behavior. Silverlight doesn't have Style triggers so you'll need to use the VisualStateManager. Do you have Expression Blend? If so you can see the default control template by dragging a button onto the designer, right click -> edit template -> edit a copy.

EDIT

I've included the default control template for Button as extracted by Blend. Take note of the Disabled state in the VisualStateManager.

<ControlTemplate TargetType="Button">
  <Grid>
    <VisualStateManager.VisualStateGroups>
      <VisualStateGroup x:Name="CommonStates">
        <VisualState x:Name="Normal"/>
        <VisualState x:Name="MouseOver">
          <Storyboard>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="BackgroundAnimation" Storyboard.TargetProperty="Opacity">
              <SplineDoubleKeyFrame KeyTime="0" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
              <SplineColorKeyFrame KeyTime="0" Value="#F2FFFFFF"/>
            </ColorAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)">
              <SplineColorKeyFrame KeyTime="0" Value="#CCFFFFFF"/>
            </ColorAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)">
              <SplineColorKeyFrame KeyTime="0" Value="#7FFFFFFF"/>
            </ColorAnimationUsingKeyFrames>
          </Storyboard>
        </VisualState>
        <VisualState x:Name="Pressed">
          <Storyboard>
            <ColorAnimationUsingKeyFrames Storyboard.TargetName="Background" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)">
              <SplineColorKeyFrame KeyTime="0" Value="#FF6DBDD1"/>
            </ColorAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="BackgroundAnimation" Storyboard.TargetProperty="Opacity">
              <SplineDoubleKeyFrame KeyTime="0" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)">
              <SplineColorKeyFrame KeyTime="0" Value="#D8FFFFFF"/>
            </ColorAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
              <SplineColorKeyFrame KeyTime="0" Value="#C6FFFFFF"/>
            </ColorAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)">
              <SplineColorKeyFrame KeyTime="0" Value="#8CFFFFFF"/>
            </ColorAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)">
              <SplineColorKeyFrame KeyTime="0" Value="#3FFFFFFF"/>
            </ColorAnimationUsingKeyFrames>
          </Storyboard>
        </VisualState>
        <VisualState x:Name="Disabled">
          <Storyboard>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="DisabledVisualElement" Storyboard.TargetProperty="Opacity">
              <SplineDoubleKeyFrame KeyTime="0" Value=".55"/>
            </DoubleAnimationUsingKeyFrames>
          </Storyboard>
        </VisualState>
      </VisualStateGroup>
      <VisualStateGroup x:Name="FocusStates">
        <VisualState x:Name="Focused">
          <Storyboard>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity">
              <SplineDoubleKeyFrame KeyTime="0" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
          </Storyboard>
        </VisualState>
        <VisualState x:Name="Unfocused"/>
      </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <Border
      x:Name="Background"
      Background="White"
      BorderBrush="{TemplateBinding BorderBrush}"
      BorderThickness="{TemplateBinding BorderThickness}"
      CornerRadius="3">
      <Grid Margin="1" Background="{TemplateBinding Background}">
        <Border x:Name="BackgroundAnimation" Opacity="0" Background="#FF448DCA"/>
        <Rectangle x:Name="BackgroundGradient">
          <Rectangle.Fill>
            <LinearGradientBrush EndPoint=".7,1" StartPoint=".7,0">
              <GradientStop Color="#FFFFFFFF" Offset="0"/>
              <GradientStop Color="#F9FFFFFF" Offset="0.375"/>
              <GradientStop Color="#E5FFFFFF" Offset="0.625"/>
              <GradientStop Color="#C6FFFFFF" Offset="1"/>
            </LinearGradientBrush>
          </Rectangle.Fill>
        </Rectangle>
      </Grid>
    </Border>
    <ContentPresenter
      x:Name="contentPresenter"
      HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
      Margin="{TemplateBinding Padding}"
      VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
      Content="{TemplateBinding Content}"
      ContentTemplate="{TemplateBinding ContentTemplate}"/>
    <Rectangle
      x:Name="DisabledVisualElement"
      Fill="#FFFFFFFF"
      RadiusX="3"
      RadiusY="3"
      IsHitTestVisible="false"
      Opacity="0"/>
    <Rectangle
      x:Name="FocusVisualElement"
      Stroke="#FF6DBDD1"
      StrokeThickness="1"
      RadiusX="2"
      RadiusY="2"
      Margin="1"
      IsHitTestVisible="false"
      Opacity="0"/>
  </Grid>
</ControlTemplate>
Josh Einstein
I haven' changed the buttons template, but nothing shows up when it is disabled. I have the MS BureauBlue theme applied if that makes any difference..
andrej351
Oh well that certainly has replaced the template. All those themes are buggy as hell, in my opinion. You'll probably need to modify the control template a little.
Josh Einstein
Yep, you're exactly right. The BureauBlue template hides the ContentPresenter when the Button is disabled (god knows why). I basically removed its whole disabled state and replaced it with the one above and it works fine. I don't have blend so that was quite handy. Thank you very much!
andrej351
A: 

Lowering the Opacity property of the button a little bit might help making it look like disabled.

Hadi Eskandari