Skip to content
Bruno Sonnino
Menu
  • Home
  • About
Menu

Element Binding e 3D em Silverlight 3

Posted on 22 March 2009

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:

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:

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:

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.

Post navigation

Criando uma aplicação LOB com Silverlight e WCF
Campeão ImagineCup Brasil 2009

6 thoughts on “Element Binding e 3D em Silverlight 3”

  1. André Baltieri says:
    23 March 2009 at 11:37

    Bruno, vendo este artigo não posso deixar de comentar, isso é fantástico. Parabéns pelo seu trabalho e obrigado por compartilhar informação.

    Um abraço.

    Atenciosamente,

    André Baltieri
    andre.baltieri@insidedotnet.com.br
    http://www.insidedotnet.com.br/

    Reply
  2. bsonnino says:
    23 March 2009 at 11:46

    Fico contente que gostou. Aguarde, quero postar mais sobre novidades do Silverlight.

    Reply
  3. Andre Baltieri says:
    6 April 2009 at 21:32

    Bruno, tem algum tutorial que você recomenda sobre StackPanels e alinhamento dos objetos na tela. estou tendo problemas com isto.

    Abraços e obrigado

    Reply
  4. bsonnino says:
    7 April 2009 at 04:06

    Dê uma olhada em um artigo que escrevi com menu filho para o MSDN: http://www.microsoft.com/brasil/msdn/Tecnologias/netframework/objetos.mspx

    Bruno

    Reply
  5. Maykon says:
    15 December 2009 at 10:48

    Estou criando objetos em run-time e precisa aplicar um binding, você teria algum site onde possa ver como é feito esse codigo todo no code behind?

    Reply
  6. bsonnino says:
    15 December 2009 at 10:59

    Dê uma olhada aqui: http://www.c-sharpcorner.com/UploadFile/dhananjaycoder/Runtimedatabinding04202009041801AM/Runtimedatabinding.aspx

    Bruno

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

  • November 2023
  • October 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • June 2022
  • April 2022
  • March 2022
  • February 2022
  • January 2022
  • July 2021
  • June 2021
  • May 2021
  • April 2021
  • March 2021
  • February 2021
  • January 2021
  • December 2020
  • October 2020
  • September 2020
  • April 2020
  • March 2020
  • January 2020
  • November 2019
  • September 2019
  • August 2019
  • July 2019
  • June 2019
  • April 2019
  • March 2019
  • February 2019
  • January 2019
  • December 2018
  • November 2018
  • October 2018
  • September 2018
  • August 2018
  • July 2018
  • June 2018
  • May 2018
  • November 2017
  • October 2017
  • September 2017
  • August 2017
  • June 2017
  • May 2017
  • March 2017
  • February 2017
  • January 2017
  • December 2016
  • November 2016
  • October 2016
  • September 2016
  • August 2016
  • July 2016
  • June 2016
  • May 2016
  • April 2016
  • March 2016
  • February 2016
  • October 2015
  • August 2013
  • May 2013
  • February 2012
  • January 2012
  • April 2011
  • March 2011
  • December 2010
  • November 2009
  • June 2009
  • April 2009
  • March 2009
  • February 2009
  • January 2009
  • December 2008
  • November 2008
  • October 2008
  • July 2008
  • March 2008
  • February 2008
  • January 2008
  • December 2007
  • November 2007
  • October 2007
  • September 2007
  • August 2007
  • July 2007
  • Development
  • English
  • Português
  • Uncategorized
  • Windows

.NET .NET Core ADS Algorithms Animations asp.NET Authentication Backup C# Debugging Delphi Dependency Injection Desktop Bridge Desktop icons Electron JSON Linq MVVM NTFS Open Source OpenXML OzCode P/Invoke PowerShell PWA Sensors Silverlight sql server Surface Dial Testing Tools TypeScript UI Unit Testing UWP Visual Studio VS Code WebView2 Windows Windows 10 Windows Protection WPF XAML XML Zip

  • Entries RSS
  • Comments RSS
©2023 Bruno Sonnino | Design: Newspaperly WordPress Theme