sábado, 19 de março de 2011

Continuando o artigo anterior – Utilizando MEF com Silverlight na prática

No artigo anterior, criamos dois novos UserControl’s com atributos [Export] e mostrei como visualizá-los dentro da MainPage usando MEF.

Uma vez que o MEF criou uma instância de uma classe que foi exportada, toda vez que solicitarmos novamente ao catálogo essa mesma classe, será retornada a mesma instância.

Para deixar isso bem claro, coloquei um textblock que informa a data e hora em que o MEF criou o objeto. No caso de precisarmos atualizar essa data sem criar uma nova instância, teremos que simular um evento que indica quando aquele usercontrol foi solicitado novamente ao Catálogo.

Uma solução para isso é criarmos uma interface que chama um método para realizar essa tarefa de atualizar a data/hora do textblock. Mãos à obra!

Vamos criar duas interfaces: uma interface chamada IMainPage que conterá um método MostrarTela(string contrato), e outra interface chamada ITela que conterá um método Activate().

Crie uma pasta chamada “Contratos” dentro do projeto silverlight e adicione essas duas interfaces da seguinte maneira:

//interface IMainPage
namespace SilverlightApplication1.contracts
{
    public interface IMainPage
    {
        void MostrarTela(string contrato);
    }
}

//interface ITela
namespace SilverlightApplication1.contracts
{
    public interface ITela
    {
        void Activate();
    }
}


Abra o arquivo MainPage.xaml.cs e implemente a interface IMainPage. Os eventos do Click dos botões também devem ser alterados para chamar o método MostrarTela passando a string do contrato desejado como parâmetro. O conteúdo da classe inteira ficará dessa forma:

[Export("MainPageExport", typeof(UserControl))]
public partial class MainPage : UserControl, IMainPage
{
    public MainPage()
    {
        InitializeComponent();
    }

    private void Tela1_Click(object sender, RoutedEventArgs e)
    {
        MostrarTela("Tela1");
    }

    private void Tela2_Click(object sender, RoutedEventArgs e)
    {
        MostrarTela("Tela2");
    }

    #region Implementation of IMainPage
    public void MostrarTela(string contrato)
    {
        ITela tela = CatalogoMef.GetInstance<UserControl>(contrato) as ITela;
        if (tela != null)
        {
            mainPageContentControl.Content = tela;
            tela.Activate();
        }
    }
    #endregion
}

Repare na implementação do método MostrarTela que chamamos a tela com o contrato solicitado através do catálogo do MEF. Se o MEF encontrou a tela, a variável “tela” não será nula, então setamos o conteúdo do controle MainPageContentControl para o valor retornado pelo MEF e em seguida, chamamos o método Activate() da interface ITela. Esse método será implementado nos UserControl’s Tela1.xaml.cs e Tela2.xaml.cs. Veja como deve ficar:

[Export("Tela1", typeof(UserControl))]
public partial class Tela1 : UserControl, ITela
{
    public Tela1()
    {
        InitializeComponent();
    }

    #region Implementation of ITela

    public void Activate()
    {
        dataHoraCriacao.Text = DateTime.Now.ToString();
    }

    #endregion
}

Faça a mesma alteração no arquivo Tela2.xaml.cs:

[Export("Tela2", typeof(UserControl))]
public partial class Tela2 : UserControl, ITela
{
    public Tela2()
    {
        InitializeComponent();
    }

    #region Implementation of ITela

    public void Activate()
    {
        dataHoraCriacao.Text = DateTime.Now.ToString();
    }

    #endregion
}

Dessa forma, ao implementarmos a interface ITela que criamos na pasta “Contratos”, somos obrigados a implementar o método Activate. Nesse método Activate, será feita a atualização da Data e Hora do textblock.

Execute a aplicação e você verá que agora a data/hora sempre estarão atualizadas.

Neste artigo podemos concluir que através do auxílio de interfaces, podemos controlar e manter o estado das telas que foram instanciadas.

Para finalizar vamos implementar um método DeActivate() que será chamado quando a tela ficar invisível.
Para isto, altere a interface ITela e adicione um método DeActivate() da mesma forma como declarado o método Activate():

//interface ITela
namespace SilverlightApplication1.contracts
{
    public interface ITela
    {
        //método chamado quando a tela ficar vísivel
        void Activate();

        //método chamado quando a tela ficar invisível
        void DeActivate();
    }
}

Como adicionamos um método novo na interface ITela, agora precisamos implementar esse método na Tela1 e Tela2:

public void DeActivate()
{
    dataHoraCriacao.Text = "";
}

Pra concluir essa funcionalidade, vamos adicionar uma propriedade na interface IMainPage, que será uma referência à tela que está Ativa no momento:

//interface IMainPage
namespace SilverlightApplication1.contracts
{
    public interface IMainPage
    {
        //propriedade que vai guardar a referência à tela que estiver ativa
        ITela TelaAtiva { get; set; }
        void MostrarTela(string contrato);
    }
}

Em MainPage.xaml.cs, a classe toda ficará dessa maneira:

[Export("MainPageExport", typeof(UserControl))]
public partial class MainPage : UserControl, IMainPage
{
    public MainPage()
    {
        InitializeComponent();
    }

    private void Tela1_Click(object sender, RoutedEventArgs e)
    {
        MostrarTela("Tela1");
    }

    private void Tela2_Click(object sender, RoutedEventArgs e)
    {
        MostrarTela("Tela2");
    }

    #region Implementation of IMainPage

    public ITela TelaAtiva { get; set; }

    public void MostrarTela(string contrato)
    {
        if (TelaAtiva != null) TelaAtiva.DeActivate();
        TelaAtiva = CatalogoMef.GetInstance<UserControl>(contrato) as ITela;
        if (TelaAtiva == null) return;
        mainPageContentControl.Content = TelaAtiva;
        TelaAtiva.Activate();
    }
    #endregion
}

Toda vez que uma nova tela for chamada, a tela ativa atual irá executar o método DeActivate(), nesse método poderemos fazer o que acharmos necessário quando uma tela ficar invisível. Em seguida, a nova tela passa a ser ativa e então o método Activate() é chamado.


Código fonte do projeto aqui

Nenhum comentário:

Postar um comentário