jueves, 17 de febrero de 2011

Strikethrough effect for TextBlock in Silverlight

Here, I would like to introduce a new control for TextBlock to add new text effects. Concretely, the Strikethrough effect that Silverlight does not support.
First, you need to create a new control by inheriting to Control. The best way would be to inherit to a TextBlock element, but this control is marked as sealed so we will need to include manually all properties that we need.

Second, create a new resource dictionary defining the template for this new control. This template will be composed by two elements: Line and TextBlock.

<ControlTemplate TargetType="ext:iTextBlock">
                    <Grid>
                        <Line x:Name="PART_lStrikethrough" Stroke="{TemplateBinding Foreground}" StrokeThickness="1" Visibility="Collapsed"/>
                        <TextBlock x:Name="PART_tbText"
                                   TextTrimming="WordEllipsis"
                                   Foreground="{TemplateBinding Foreground}"
                                   Text="{TemplateBinding Text}"/>
                    </Grid>
</ControlTemplate>




Remember, if you want that your control be themable, you need to place this resourcedicionary in the folder themes\generic.xaml and set the property DefaultStyleKey to typeof(the name of your control).

Third, define the overriden method OnApplyTemplate in order to retrieve the textblock and line elements that you created in the second step.

Then, define an enum with all new features as text effect that you would like to support and create a new dependency property to enable that user sets this in xaml. In this dependency property, I suggest always to define a default value and the changed event of the PropertyMetadata.


        /// <summary>
        /// Dependency property to set the effect to the textblock element.
        /// </summary>
        public static readonly DependencyProperty TextEffectProperty =
            DependencyProperty.Register("TextEffect", typeof(Effects), typeof(iTextBlock), new PropertyMetadata(Effects.None, OnEffectChanged));

        /// <summary>
        /// Effect for text block element.
        /// </summary>
        public Effects TextEffect
        {
            get
            {
                return (Effects)this.GetValue(TextEffectProperty);
            }

            set
            {
                this.SetValue(TextEffectProperty, value);
            }
        }

Finally, attach to the size changed event and place the Line element in the middle:

        private void OnSizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (this.lStrikethrough != null)
            {
                this.lStrikethrough.X1 = 0;
                this.lStrikethrough.Y1 = e.NewSize.Height / 2;
                this.lStrikethrough.X2 = e.NewSize.Width - 1;
                this.lStrikethrough.Y2 = this.lStrikethrough.Y1;
            }
        }

No hay comentarios:

Publicar un comentario