Monday, March 7, 2011

Dica de desempenho em WPF TreeView

Eu tive problema quando usei costume TreeView com costume TreeViewItem.
Quando o data binding executou, o Tree criou todos os itens no mesmo tempo – o que causou o CPU alto, muita memória , e a tela que teve o TreeView não estava respondendo por alguns segundos.
No fim da minha pesquisa eu achei que:
O VS 2010 profiler não ajudou e não achou a razão do problema, ele apontou para MeasureOverride método  do que a razão verdadeira que foi que eu deletei um trigger no xaml style do custom TreeViewItem -  e isso não deixou a virtualização do TreeView funcionar normal.
A falta de virtualização forçou o Tree criar todos os TreeViewItems quando o data binding para o ItemsSource mudou.

Reparação:
No xaml que contém  a declaração do TreeViewItem (ou class que herdar ele):
Na linha que começa assim :
<Style TargetType="{x:Type TreeViewItem}">
dentro do triggers que começa assim:
<ControlTemplate.Triggers>
as seguintes linhas não podem remover, ou, podem usar outro multi trigger que causa o mesmo resultado:
<Trigger Property="IsExpanded" Value="false">
    <Setter Property="Visibility" TargetName="ItemsHost" Value="Collapsed"/>
</Trigger>
Com essas linhas, o TreeView não vai criar todos filhos/netos até o usuário vai expandir os items "pais" primeiro.
Isso pode fazer os desempenhos muito mais rápido.

Friday, March 4, 2011

Nova infraestratura para desenvolver aplicações de P2P passo a passo

Terminei de publicar em Inglês 3 postagens que explicam como usar a minha infraestrutura que escrevi para facilitar fazer sincronização entre aplicações que usam P2P , doque usar o modelo regular de "cliente-servidor".
Pensei que antes que eu vou traduzir isso para português vale a pena fazer links para quem quiser em Inglês:
  1. Part 1 - A primeira parte que explica porque eu fiz essa infraestrutura e qual os problemas que ela resolve comparando modelo de cliente-servidor.
  2. Part 2 - Tutorial com demonstração do aplicação de demo.
  3. Part 3 - Como desenvolver sua própria aplicação com essa infraestrutura.
Ficarei feliz em receber comentários e perguntas.

Thursday, February 10, 2011

CCCheck has stopped working

De repente eu começei receber essa mensagem quando faço "build" para um projeto.

image

Problema: O projeto configurando para trabalhar com baseline arquivo nos opoçoes do CodeContracts.

image

Eu acho que isso acontece depois que eu baixei versão pelo source control e isso mudou various arquivos para "read only" (somente leitura) inclusivo o baseline.xml.new arquivo.

A janela do output window mostra o exception:

CodeContracts: Roniz.WCF.P2P.Messages: Unhandled Exception: System.UnauthorizedAccessException: Access to the path …\baseline.xml.new' is denied.

soluçao:

Tirar o "read only" atributo do arquvio/s

Saturday, February 5, 2011

Blog em inglês

Tenho tambêm o mesmo blog mas mais atualizado em inglês… gerlamente eu escrevo primeiro em ingles antes de traduzir para português.
Para quem quiser e nesse endereço:
http://www.roniz.net/

ObservableDictionary do DR WPF com dispatcher

Eu uso o ObservableDictionary que DR WPF forneceu para WPF , porem tive problemas quando mudei o dicionario em thread diferente do que o thread que o dicionario foi criado – os eventos: CollectionChanged / PropertyChanged executaram em thread diferente. (gente como falo "thread" em portugues, mas na nossa lingua de programadores ??? סמיילי )

Entao eu mudei o codigo um pouco para suportar isso. As mudanças sao:

1. Nos constructors adicionei parâmetros opcionais para o dispatcher & DispatcherPriority (padrao para DispatcherPriority.DataBind).

public ObservableDictionary(Dispatcher dispatcher = null,DispatcherPriority dispatcherPriority = DispatcherPriority.DataBind)

{

    _dispatcher = dispatcher;

    _dispatcherPriority = dispatcherPriority;

    _keyedEntryCollection = new KeyedDictionaryEntryCollection<TKey>();

}

2. Nos methodos que executa os OnCollectionChanged and OnPropertyChanged eventos verifiquei se o dispatcher nao e null – e ai executei o evento com o dispatcher no lugar de executar ele no thread que chamou ele.

protected
virtual
void OnCollectionChanged(NotifyCollectionChangedEventArgs args)

{

    var handler = CollectionChanged;

    if (handler != null)

    {

    if (_dispatcher != null)

    {

        if (_dispatcher.CheckAccess())

        {

            handler(this, args);

        }

        else

        {

            _dispatcher.Invoke((Action)(() => handler(this, args)), _dispatcherPriority);

        }

    }

    else

    {

        handler(this, args);

    }

    }

}

O codigo completo esta aqui.