A versão beta do Silverlight 3 foi lançada no Mix 2009 e trouxe diversas novidades. Entre elas estão o Element Binding e a possibilidade de simular 3D nas aplicações.

O Element Binding é um tipo de data binding já existente no WPF, mas que não tinha sido implementado no Silverlight 2. No Silverlight 2 podiamos fazer ligação da interface com os dados de uma classe interna, mas não podíamos ligar 2 as propriedades de dois elementos visuais. Por exemplo, se quiséssemos colocar um TextBlock e um Slider na janela e mostrar a posição do Slider no TextBlock, deveríamos criar uma classe no código e ligar os dados da classe aos dois componentes. O código ficaria assim:

Code behind:

namespace SL2Binding

{

    public class Binder : INotifyPropertyChanged

    {

        private double posicao;

        public double Posicao

        {

            get { return posicao; }

            set

            {

                posicao = value;

                if (PropertyChanged != null)

                    PropertyChanged(this, new PropertyChangedEventArgs(“Posicao”));

            }

        }

 

        #region INotifyPropertyChanged Members

 

        public event PropertyChangedEventHandler PropertyChanged;

 

        #endregion

    }

 

    public partial class MainPage : UserControl

    {

        public MainPage()

        {

            InitializeComponent();

        }

    }

}

 

XAML:

<UserControl x:Class=”SL2Binding.MainPage”

    xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”

    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”

             xmlns:local=”clr-namespace:SL2Binding”

             Width=”400″ Height=”300″>

    <UserControl.Resources>

        <local:Binder x:Key=”binder” />

    </UserControl.Resources>

    <Grid x:Name=”LayoutRoot” Background=”White”>

        <StackPanel Orientation=”Horizontal”>

            <Slider Width=”150″ Margin=”5″ Value=”{Binding Source={StaticResource binder}, Path=Posicao, Mode=TwoWay}”/>

            <TextBlock VerticalAlignment=”Center”  Margin=”5″ Text=”{Binding Source={StaticResource binder}, Path=Posicao, Mode=TwoWay}”/>

        </StackPanel>

    </Grid>

</UserControl>

 

Embora isto funcione, é um pouco complicado: precisamos criar uma classe de ligação que implementa a interface INotifyPropertyChanged, declará-la no XAML e fazer data binding dos dois elementos com ela.  Com a introdução do Element Binding no Silverlight 3, as coisas ficam muito mais fáceis: não precisamos implementar classes no código e o XAML fica muito mais simples:

<UserControl x:Class=”SL2Binding.MainPage”

    xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”

    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”

             Width=”400″ Height=”300″>

    <Grid x:Name=”LayoutRoot” Background=”White”>

        <StackPanel Orientation=”Horizontal”>

            <Slider x:Name=”slider” Width=”150″ Margin=”5″ />

            <TextBlock x:Name=”textBlock” VerticalAlignment=”Center”  Margin=”5″ Text=”{Binding ElementName=slider, Path=Value, Mode=OneWay}”/>

        </StackPanel>

    </Grid>

</UserControl>

 

Precisamos apenas de um binding do texto do TextBlock com o slider e temos exatamente o mesmo comportamento do código anterior.

Simultaneamente à introdução do Element Binding, o Silverlight 3 também trouxe, entre outras coisas, uma simulação de 3D. Não é um 3D real, mas é muito simples de usar e deve satisfazer as necessidades de grande parte dos usuários: o Silverlight 3 permite criar a projeção de um plano girá-la nos eixos X, Y ou Z. Por exemplo. Se tivermos uma janela como esta:

<Grid x:Name=”rotateGrid” Margin=”10″ Background=”LightGray” >

    <Grid.RowDefinitions>

        <RowDefinition Height=”30″ />

        <RowDefinition Height=”30″ />

        <RowDefinition Height=”30″ />

        <RowDefinition Height=”30″ />

        <RowDefinition Height=”*” />

    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>

        <ColumnDefinition Width=”*” />

        <ColumnDefinition Width=”2*” />

    </Grid.ColumnDefinitions>

    <TextBlock Text=”Nome” Grid.Row=”0″ Margin=”5″/>

    <TextBlock Text=”Endereço” Grid.Row=”1″ Margin=”5″/>

    <TextBlock Text=”Cidade” Grid.Row=”2″ Margin=”5″/>

    <TextBlock Text=”Estado” Grid.Row=”3″ Margin=”5″/>

    <TextBox Grid.Row=”0″ Grid.Column=”1″ HorizontalAlignment=”Stretch” Margin=”5″ />

    <TextBox Grid.Row=”1″ Grid.Column=”1″ HorizontalAlignment=”Stretch” Margin=”5″ />

    <TextBox Grid.Row=”2″ Grid.Column=”1″ HorizontalAlignment=”Stretch” Margin=”5″ />

    <TextBox Grid.Row=”3″ Grid.Column=”1″ HorizontalAlignment=”Stretch” Margin=”5″ />

    <StackPanel Orientation=”Horizontal” Grid.Row=”4″ Grid.Column=”1″ Margin=”5″

                HorizontalAlignment=”Center” VerticalAlignment=”Top”>

        <Button Content=”Ok” Height=”27″ Width=”75″ Margin=”5″/>

        <Button Content=”Cancelar” Height=”27″ Width=”75″ Margin=”5″/>

    </StackPanel>

</Grid>

 

Podemos girá-la usando o seguinte markup:

<Grid.Projection>

    <PlaneProjection RotationY=”30″/>

</Grid.Projection>

 

Estamos aqui indicando que queremos girar a grid em 30º ao redor do eixo Y. Ao executarmos o programa, temos a seguinte figura:

 Figura 1

Note que, embora a figura esteja girada, ela é perfeitamente funcional. Da mesma maneira que giramos em torno do eixo Y, podemos ainda girar o plano em torno dos eixos X e Z. Os eixos estão dispostos como na figura abaixo:

 Figura 2

Agora, podemos juntar as duas partes (Element Binding e 3D) fazer o painel girar na horizontal (rotação no eixo Y) com o uso de um slider, sem precisar usar código. Para isso, usamos o seguinte XAML:

<UserControl x:Class=”SL3Plane.MainPage”

    xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”

    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”

    Width=”400″ Height=”300″>

    <Grid x:Name=”LayoutRoot” Background=”White”>

        <Grid.RowDefinitions>

            <RowDefinition Height=”*” />

            <RowDefinition Height=”30″ />

        </Grid.RowDefinitions>

        <Grid x:Name=”rotateGrid” Margin=”10″ Background=”LightGray” >

            <Grid.Projection>

                <PlaneProjection x:Name=”Projecao” />

            </Grid.Projection>

            <Grid.RowDefinitions>

                <RowDefinition Height=”30″ />

                <RowDefinition Height=”30″ />

                <RowDefinition Height=”30″ />

                <RowDefinition Height=”30″ />

                <RowDefinition Height=”*” />

            </Grid.RowDefinitions>

            <Grid.ColumnDefinitions>

                <ColumnDefinition Width=”*” />

                <ColumnDefinition Width=”2*” />

            </Grid.ColumnDefinitions>

            <TextBlock Text=”Nome” Grid.Row=”0″ Margin=”5″/>

            <TextBlock Text=”Endereço” Grid.Row=”1″ Margin=”5″/>

            <TextBlock Text=”Cidade” Grid.Row=”2″ Margin=”5″/>

            <TextBlock Text=”Estado” Grid.Row=”3″ Margin=”5″/>

            <TextBox Grid.Row=”0″ Grid.Column=”1″ HorizontalAlignment=”Stretch” Margin=”5″ />

            <TextBox Grid.Row=”1″ Grid.Column=”1″ HorizontalAlignment=”Stretch” Margin=”5″ />

            <TextBox Grid.Row=”2″ Grid.Column=”1″ HorizontalAlignment=”Stretch” Margin=”5″ />

            <TextBox Grid.Row=”3″ Grid.Column=”1″ HorizontalAlignment=”Stretch” Margin=”5″ />

            <StackPanel Orientation=”Horizontal” Grid.Row=”4″ Grid.Column=”1″ Margin=”5″

                        HorizontalAlignment=”Center” VerticalAlignment=”Top”>

                <Button Content=”Ok” Height=”27″ Width=”75″ Margin=”5″/>

                <Button Content=”Cancelar” Height=”27″ Width=”75″ Margin=”5″/>

            </StackPanel>

        </Grid>

        <Slider Grid.Row=”1″ Width=”150″ Minimum=”0″ Maximum=”180″

           Value=”{Binding ElementName=Projecao, Path=RotationY,

                     Mode=TwoWay}” />

    </Grid>

</UserControl>

 

Demos um nome à projeção para poder fazer Binding com ela e colocamos um slider na página, para poder girar o plano. Ao executarmos o projeto, vemos que o slider gira o plano sem que haja a necessidade de escrever código. Porém, ao girar mais de 90º vemos um efeito indesejado: o 3D do Silverlight é apenas uma simulação e estamos vendo a frente do painel, invertida:

Figura3

Mesmo assim, a tela continua funcional, podemos digitar nas caixas de texto normalmente. Com quase toda certeza, não é este efeito que você está procurando, e devemos dar um jeito nisso.  Para simular o efeito 3D devemos ter dois painéis, um para a frente e outro para o fundo. Criamos então o painel do fundo e deixamos com visibilidade Collapsed, para que não seja mostrado:

<Grid x:Name=”gridFundo” Background=”Aquamarine” Visibility=”Collapsed”

      RenderTransformOrigin=”0.5,0.5″>

    <TextBlock Text=”Verso do painel” FontFamily=”Tahoma”

               FontSize=”24″

               HorizontalAlignment=”Center” VerticalAlignment=”Center”

               RenderTransformOrigin=”0.5,0.5″>

        <TextBlock.RenderTransform>

            <RotateTransform Angle=”45″ />

        </TextBlock.RenderTransform>

    </TextBlock>

</Grid>

 

Este painel contém apenas um TextBlock para exemplificar, mas poderíamos colocar aí qualquer componente (um exemplo seria simular uma ficha, mostrando a frente e o verso dos dados). Para fazer a troca dos painéis devemos usar code behind, ativado pelo evento ValueChanged do slider:

private double anguloAnt;

 

private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)

{

    double anguloAtu = (sender as Slider).Value;

 

    if ((anguloAnt < 90 && anguloAtu >= 90 ) ||

        (anguloAnt > 90 && anguloAtu <= 90 ))

    {

        MostraGrids(anguloAtu);

    }

    anguloAnt = anguloAtu;

}

 

private void MostraGrids(double angulo)

{

    if (angulo < 90)

    {

        gridFrente.Visibility = Visibility.Visible;

        gridFundo.Visibility = Visibility.Collapsed;

    }

    else

    {

        gridFrente.Visibility = Visibility.Collapsed;

        gridFundo.Visibility = Visibility.Visible;

    }

}

 

Temos uma variável para guardar o ângulo atual. Quando o ângulo atual passa de 90º e o anterior é menor que 90º ou vice versa, mostramos uma grid e escondemos a outra. Temos que fazer um pequeno truque no painel de fundo:  quando estamos girando em torno do eixo Y (rotação na horizontal), o painel do fundo fica invertido. Podemos solucionar isso aplicando uma transformação que inverte o painel:

<Grid x:Name=”gridFundo” Background=”Aquamarine” Visibility=”Collapsed”

      RenderTransformOrigin=”0.5,0.5″>

    <Grid.RenderTransform>

        <ScaleTransform x:Name=”gridTransform” ScaleX=”-1″/>

    </Grid.RenderTransform>

    <TextBlock Text=”Verso do painel” FontFamily=”Tahoma” FontSize=”24″

               HorizontalAlignment=”Center” VerticalAlignment=”Center”

               RenderTransformOrigin=”0.5,0.5″>

        <TextBlock.RenderTransform>

            <RotateTransform Angle=”45″ />

        </TextBlock.RenderTransform>

    </TextBlock>

</Grid>

 

Desta maneira, mostramos o painel da frente e do verso usando os novos recursos de 3D e element binding do Silverlight 3.

Figura 4