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();
        }
    }
}
C#

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>
XML

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>
XML

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>
XML

Podemos girá-la usando o seguinte markup:

<Grid.Projection>
    <PlaneProjection RotationY="30"/>
</Grid.Projection>
XML

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>
XML

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>
XML

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;
    }
}
C#

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>
XML

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

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 *

  • May 2025
  • December 2024
  • October 2024
  • August 2024
  • July 2024
  • June 2024
  • 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 AI Algorithms asp.NET Backup C# Debugging Delphi Dependency Injection Desktop Bridge Desktop icons Entity Framework JSON Linq Mef Minimal API MVVM NTFS Open Source OpenXML OzCode PowerShell Sensors Silverlight Source Code Generators sql server Surface Dial Testing Tools TypeScript UI Unit Testing UWP Visual Studio VS Code WCF WebView2 WinAppSDK Windows Windows 10 Windows Forms Windows Phone WPF XAML Zip

  • Entries RSS
  • Comments RSS
©2025 Bruno Sonnino | Design: Newspaperly WordPress Theme
Menu
  • Home
  • About