Archive for the ‘.NET Framework’ Category

ListBox com Header no WPF

fevereiro 22, 2012

Há algum tempo precisei usar ListBox em uma aplicação WPF, porém precisava que o mesmo tivesse um Header, então decidi criar um estilo alterando a Template do ListBox para que o mesmo passasse a ter um Header.
Para começar criei uma classe chamada MeuListBox herdando da classe ListBox, depois registrei uma DependencyProperty chamada Header:


public class MeuListBox : ListBox
{
    public FrameworkElement Header
    {
        get { return (FrameworkElement)GetValue(HeaderProperty); }
        set { SetValue(HeaderProperty, value); }
    }

    public static readonly DependencyProperty HeaderProperty =
        DependencyProperty.Register("Header", typeof(FrameworkElement), typeof(Grid));
}

Feito isso, criei um estilo para que pudesse alterar a Template do ListBox:

<Style x:Key="ListBoxComHeader"
       TargetType="{x:Type ctl:MeuListBox}">
    <Setter Property="HorizontalContentAlignment"
            Value="Stretch" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ctl:MeuListBox}">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>
                    <Border Grid.Column="0"
                            Width="{Binding ElementName=Items, Path=ActualWidth}">
                        <ContentPresenter Margin="2,0,0,0"
                                          Content="{Binding Path=Header, RelativeSource={RelativeSource TemplatedParent}}" />
                    </Border>
                    <ScrollViewer Grid.Row="1"
                                  CanContentScroll="False"
                                  Name="scroll"
                                  Focusable="false"
                                  Padding="{TemplateBinding Padding}">
                        <ItemsPresenter Name="Items"
                                        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                    </ScrollViewer>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Como podemos ver no código acima, coloquei um Grid, esse Grid possui duas linhas, na primeira linha coloquei uma borda definindo a largura de acordo com a propriedade ActualWidth do controle Items (ItemsPresenter – itens do ListBox) e, dentro dessa, um ContentPresenter, sendo que seu conteúdo está fazendo Binding com a propriedade Header (DependencyProperty) que criei na minha classe MeuListBox. Nesse ContentPresenter defini a margem como 2,0,0,0 para que os itens ficassem alinhados ao Header.
Já na segunda linha, temos um ScrollViewer e dentro dele temos o ItemsPresenter.
Depois disso feito, devemos agora aplicar o estilo no nosso ListBox e definir a propriedade Header:

<ctl:MeuListBox x:Name="listBox1"
                Margin="5"
                Style="{StaticResource ListBoxComHeader}">
    <ctl:MeuListBox.Header>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="100" />
                <ColumnDefinition Width="300" />
                <ColumnDefinition Width="100" />
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Column="0"
                       Text="Nome"
                       FontWeight="Bold"
                       HorizontalAlignment="Left"
                       Foreground="Black" />
            <TextBlock Grid.Column="1"
                       Text="Idade"
                       FontWeight="Bold"
                       HorizontalAlignment="Center"
                       Foreground="Black" />
            <TextBlock Grid.Column="2"
                       Text="Cidade"
                       FontWeight="Bold"
                       HorizontalAlignment="Center"
                       Foreground="Black" />
            <TextBlock Grid.Column="3"
                       Text="Estado"
                       FontWeight="Bold"
                       HorizontalAlignment="Center"
                       Foreground="Black" />
        </Grid>
    </ctl:MeuListBox.Header>
    <ctl:MeuListBox.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="100" />
                    <ColumnDefinition Width="300" />
                    <ColumnDefinition Width="100" />
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Column="0"
                           Text="{Binding Nome}"
                           HorizontalAlignment="Left"
                           Foreground="Black" />
                <TextBlock Grid.Column="1"
                           Text="{Binding Idade}"
                           HorizontalAlignment="Center"
                           Foreground="Black" />
                <TextBlock Grid.Column="2"
                           Text="{Binding Cidade}"
                           HorizontalAlignment="Center"
                           Foreground="Black" />
                <TextBlock Grid.Column="3"
                           Text="{Binding Estado}"
                           HorizontalAlignment="Center"
                           Foreground="Black" />
            </Grid>
        </DataTemplate>
    </ctl:MeuListBox.ItemTemplate>
</ctl:MeuListBox>

Se observarmos, no Header temos um Grid contendo quatro colunas, e claro, no ItemTemplate também temos um Grid com as mesmas quatro colunas, ou seja, a estrutura do Header deve ser exatamente a mesma do ItemTemplate para que as colunas fiquem alinhadas.

Abaixo, podemos ver o resultado final:

 

Como pudemos ver no exemplo acima, para que todos os nossos ListBoxes tenham Header basta definirmos o estilo e também a propriedade Header.

Como no Header podemos colocar qualquer controle, podemos colocar botões, checkbox, etc.

Abaixo, segue projeto, o mesmo está nomeado como ListBoxSample.doc, favor renomear para .zip, pois não consigo anexar arquivos .zip no WordPress.
ListBox Sample

Anúncios

ASP.NET Menu no Safari

janeiro 30, 2011

Há alguns dias precisava que uma aplicação ASP.NET funcionasse no Safari (IPad) mas me deparei com um problema, o menu não funcionava.
Procurando pela internet encontrei uma discussão que mostrava o seguinte código:

if (Request.ServerVariables["http_user_agent"].IndexOf("Safari", StringComparison.CurrentCultureIgnoreCase) != -1)
{
    ClientTarget = "uplevel";
}

Com o código acima verificamos se o browser é o Safari, depois atribuimos à propriedade ClientTarget o valor “uplevel” (especifica compatibilidades equivalentes ao Internet Explorer 6.0).

A propriedade ClientTarget nos permite sobrescrever a detecção automática das compatibilidades do browser e especificar como a página deve ser renderizada.

O código deve ser colocado no método OnPreInit da página. Como a MasterPage não possui esse método é necessário que seja colocado em todas as páginas que possuem o menu.
Para facilitar podemos criar uma classe herdando da classe Page e sobrescrever o método OnPreInit:

public class PaginaPadrao : Page
{
    protected override void OnPreInit(EventArgs e)
    {
        if (Request.ServerVariables["http_user_agent"].IndexOf("Safari", StringComparison.CurrentCultureIgnoreCase) != -1)
        {
            ClientTarget = "uplevel";
        }
        base.OnPreInit(e);
    }
}

Agora nossas páginas deverão herdar da classe PaginaPadrao:

public partial class Default : PaginaPadrao
{
    protected void Page_Load(object sender, EventArgs e)
    {
    }
}

Feito isso toda página quando aberta executará o método OnPreInit da classe PaginaPadrao fazendo com que o menu funcione sem problemas no Safari.

Artigos no MSDN

janeiro 29, 2011

Tive a honra de escrever seis artigos para o MSDN (Microsoft Developer Network), são eles:

Agradeço ao João Paulo Clementi pela oportunidade e à todos que me apoiaram.

Task Dialog

janeiro 24, 2010

Presentes desde o Windows Vista, Task Dialogs são Message Box flexíveis onde é possível criar caixas de mensagem customizadas. Para fazer isso com código gerenciado basta usar o Windows API Code Pack for Microsoft .NET Framework descrito neste post.

Para começar vamos ver os detalhes da classe TaskDialog:

Vamos criar uma Task Dialog bem simples, contendo apenas Caption e Text:

if (TaskDialog.IsPlatformSupported)
{
    TaskDialog myDialog = new TaskDialog();
    myDialog.Caption = "Título";
    myDialog.Text = "Mensagem.";
    myDialog.StartupLocation =
        TaskDialogStartupLocation.CenterScreen;
    myDialog.Show();
}

Como podemos perceber, o primeiro passo é instanciar a classe TaskDialog, definir as propriedades necessárias e por fim chamar o método Show(). A propriedade Caption recebe uma string que determina o título e a propriedate Text também recebe uma string que determina a mensagem da Task Dialog. A propriedade IsPlatformSupported informa se Task Dialog é suportada no sistema operacional. A propriedade StartupLocation permite definir a posição da Task Dialog.

Com a propriedade InstructionText definimos a finalidade da Task Dialog e a propriedade Cancelable define se a Task Dialog pode ser cancelada ou não, definindo para true um botão “Close” é inserido no canto superior direito.

myDialog.InstructionText = "Finalidade da Task Dialog";
myDialog.Cancelable = true;

É possível adicionar uma mensagem que pode ficar oculta com botões para mostrar e esconder a mesma, para isso usamos as seguintes propriedades:

  • DetailsExpanded – Define se a mensagem fica ou não oculta, sendo que o padrão é false.
  • DetailsExpandedText – Define a mensagem.
  • DetailsCollapsedLabel – É o texto que fica no botão para mostrar a mensagem.
  • DetailsExpandedLabel – É o texto que fica no botão para ocultar a mensagem.
  • ExpansionMode – Determina o local da mensagem oculta, podendo ser acima ou abaixo dos botões de mostrar / ocultar a mensagem.
myDialog.DetailsExpanded = true;
myDialog.DetailsExpandedText = "Detalhes...";
myDialog.DetailsCollapsedLabel = "Mostrar";
myDialog.DetailsExpandedLabel = "Ocultar";
myDialog.ExpansionMode =
    TaskDialogExpandedDetailsLocation.ExpandContent;

Pode-se adicionar controles, sendo eles:

  • StandardButtons
    –> Cancel
    –> Close
    –> No
    –> Ok
    –> Retry
    –> Yes
  • Buttons (Customizados)
  • CommandLinks
  • RadioButtons

Usando StandardButtons, podemos usar a lógica OR para os botões adicionados e atribuir o método Show() da nossa Task Dialog à enumeração TaskDialogResult para capturarmos o resultado.

myDialog.StandardButtons =
    TaskDialogStandardButtons.Yes |
    TaskDialogStandardButtons.No |
    TaskDialogStandardButtons.Cancel;
    TaskDialogResult result = myDialog.Show();

Em certas situações os StandardsButtons não suprem nossas necessidades, nesses casos usamos os Buttons (Customizados). Instanciamos a classe TaskDialogButton e definimos as propriedades que se fizerem necessárias, feito isso, é preciso definir um Delegate para o evento Click dos respectivos botões e, por fim, adicionar os botões em nossa Task Dialog.

TaskDialogButton continuar = new TaskDialogButton();
continuar.Default = true;
continuar.Text = "Continuar";
continuar.Click += new EventHandler(continuar_Click);

TaskDialogButton parar = new TaskDialogButton();
parar.Default = false;
parar.Text = "Parar";
parar.Click += new EventHandler(parar_Click);

myDialog.Controls.Add(continuar);
myDialog.Controls.Add(parar);

Ao invés de Buttons podemos usar os CommandLinks, cuja configuração é praticamente a mesma dos Buttons.

TaskDialogCommandLink continuar = new TaskDialogCommandLink();
continuar.Default = true;
continuar.Text = "Continuar";
continuar.Instruction = "Continua a operação.";
continuar.Click +=new EventHandler(continuar_Click);

TaskDialogCommandLink parar = new TaskDialogCommandLink();
parar.Default = false;
parar.Text = "Parar";
parar.Instruction = "Para a operação.";
parar.Click += new EventHandler(parar_Click);

myDialog.Controls.Add(continuar);
myDialog.Controls.Add(parar);

Também podemos colocar RadioButtons que, semelhante aos CommandLinks, a configuração é praticamente a mesma dos Buttons.

TaskDialogRadioButton continuar = new TaskDialogRadioButton();
continuar.Default = true;
continuar.Text = "Continuar";

TaskDialogRadioButton parar = new TaskDialogRadioButton();
parar.Default = false;
parar.Text = "Parar";

myDialog.Controls.Add(continuar);
myDialog.Controls.Add(parar);

Como na Message Box, conseguimos adicionar icone na Task Dialog utilizando a propriedade Icon.
Podemos escolher entre os seguintes icones:

  • Error
  • Information
  • Shield
  • Warning

Podemos adicionar controles ao rodapé usando as propriedades:

  • FooterCheckBoxCheccked – Determina se o checkbox no rodapé inicia selecionado ou não.
  • FooterCheckBoxText – Texto do checkbox no rodapé.
  • FooterIcon – Icone no rodapé.
  • FooterText – Texto no rodapé.
myDialog.FooterCheckBoxChecked = false;
myDialog.FooterCheckBoxText = "Tomar essa decisão para todos.";
myDialog.FooterIcon = TaskDialogStandardIcon.Warning;
myDialog.FooterText = "Texto de rodapé";

Conseguimos adicionar hyperlinks ao rodapé, o que é preciso fazer é definir a propriedade HyperlinksEnable como true, adicionar o link dentro da tag <a href> , definir um delegate para o evento HyperlinkClick e codificá-lo.

myDialog.HyperlinksEnabled = true;
myDialog.FooterText =
    "Para maiores detalhes visite nosso site:
    <a href=\"http://www.microsoft.com.br\">Microsoft</a>";
myDialog.HyperlinkClick += new
    EventHandler<TaskDialogHyperlinkClickedEventArgs>
    (myDialog_HyperlinkClick);

void myDialog_HyperlinkClick(object sender,
    TaskDialogHyperlinkClickedEventArgs e)
{
    Process.Start(e.LinkText);
}

É possível adicionar ProgressBar para mostrar ao usuário o andamento de uma operação. É preciso apenas instanciar a classe TaskDialogProgressBar e atribuí-la à propriedade ProgressBar. É possível também definir o estado do andamento da operação, são eles:

  • Error
  • Marquee
  • Normal
  • Paused
TaskDialogProgressBar progressBar =
    new TaskDialogProgressBar();
progressBar.Minimum = 0;
progressBar.Maximum = 100;
progressBar.Value = 25;
progressBar.State = TaskDialogProgressBarState.Normal;
myDialog.ProgressBar = progressBar;

Desenvolvendo aplicações .NET usando recursos do Windows 7

janeiro 13, 2010

Foi disponibilizado pela Microsoft o Windows API Code Pack for Microsoft .NET Framework que fornece uma biblioteca de códigos para desenvolvermos aplicações .NET usufruindo de alguns recursos do Windows 7 com código gerenciado.
Na versão 1.0.1 são suportados os seguintes recursos:

          • Windows 7 Taskbar
                   –>    Jump Lists, Icon Overlay, Progress Bar, Tabbed Thumbnails, and Thumbnail Toolbars
          • Windows Shell
                    –>   Windows 7 Libraries
                    –>   Windows Shell Search API support
                    –>   Explorer Browser Control
                    –>   A hierarchy of Shell Namespace entities
                    –>   Windows Shell property system
                    –>   Drag and Drop for Shell Objects
                    –>   Windows Vista and Windows 7 Common File Dialogs, including custom controls
                    –>   Known Folders and non-file system containers
          • DirectX
                    –>   Direct3D 11.0, Direct3D 10.1/10.0, DXGI 1.0/1.1, Direct2D 1.0, DirectWrite, Windows Imaging Component (WIC) APIs
         • Windows Vista and Windows 7 Task Dialogs
         • Sensor Platform APIs
         • Extended Linguistic Services APIs
         • Power Management APIs
         • Application Restart and Recovery APIs
         • Network List Manager APIs
         • Command Link control and System defined Shell icons

Para iniciarmos o desenvolvimento primeiro precisamos extrair o conteúdo do arquivo WindowsAPICodePack.zip, depois adicionar os projetos Core e Shell à nossa solução e por fim referenciar as DLLs Core.dll e Shell.dll ao projeto.
Após feito isso é só começar a desenvolver suas aplicações.