Capítulo 4: Using Server Controls Lição 2: Exploring Specialized Server Controls
Autor: quintelab | Publicado: 2011-08-15T17:10:00-07:00

Se olharmos a alguns anos atras, criar um simples calendário em uma página web era uma tarefa no minimo chata, era necessário criar tabelas, linhas e colunas, e adicinoar hyperlink nas datas, o javascript até poderia ajudar neste trabalho, mas ainda assim era uma tarefa chata.

O asp.net possui diversos controles onde o objetivo é justamente este facilitar no desenvolvimento de páginas que necessitam desses recursos. Esta lição irá falar sobre os seguinte controles que facilitam a nossa vida:
Table
Image
ImageButton
ImageMap
Calendar
FileUpload
Panel
MultiView
Wizard
Xml

The Table, TableRow, and TableCell Controls 

Antigamente, e alguns desenvolvedores até hoje utilizam tables, tr e td html. Mas sabemos que devemos evitar o uso dessas tags html e usar divs, span e etc... Porém fica dificil fazer tudo com divs, quando se tem a necessidade de exibir dados tabulados.

Estes controles do asp.net tem o mesmo objetivo da table, tr e td do html, a grande diferença é que são Server Controls e por isso podem ser criados e manipulados em tempo execução.

O controle table possui uma propriedade que é uma coleção do controle TableRow, e por sua vez o TableRow possui uma propriedade que é uma coleção dos controles TableCell. Todos eles herdam a classe WebControl, por isso possuem as propriedades comuns como Font, BackColor e ForeColor.

Adding Rows and Cells Dynamically to a Table Control

O Visual Studio permite que você crie seu controle Table pelo designer dele, simplesmente arrastando o controle para sua página e editando suas propriedades, onde terá a opção de adicionar linhas e em seguida células. Porém se irá criar tabelas estáticas que não serão manipuladas em tempo de execução é recomendado que utilize as tabelas do html, pois terão melhor performance que os Controls Server do asp.net.

O único motivo para utilizar este controle é a necessidade de manipular em tempo de execução, a baixo código explicando:
Na ToolBox arraste o Controle Table para sua página.
Vá ao arquivo de code-behind e crie o evento PreInit do seu formulário.
Dentro deste evento escreva um loop para criar 5 linhas em seu controle.
Dentro deste loop, adicione outro loop para criar 3 célular dentro de cada linha.
Dentro do último loop modifique a propriedade TableCell.Tex para identificar a linha e a coluna.
protected void Page_PreInit(object sender, EventArgs e)
{
&nbsp; Table1.BorderWidth = 1;
&nbsp; for (int row = 0; row &lt; 5; row++)&nbsp; &nbsp;
&nbsp; {
&nbsp;&nbsp;&nbsp; TableRow tr = new TableRow();&nbsp;&nbsp;&nbsp; &nbsp;
 &nbsp;&nbsp;&nbsp; for (int column = 0; column &lt; 3; column++)&nbsp;&nbsp;&nbsp; &nbsp;
 &nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TableCell tc = new TableCell();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tc.Text = string.Format("Row:{0} Cell:{1}", row, column);&nbsp;
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tc.BorderWidth = 1;&nbsp;
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tr.Cells.Add(tc);&nbsp;&nbsp;&nbsp; &nbsp;
&nbsp;&nbsp;&nbsp; }&nbsp;
&nbsp; Table1.Rows.Add(tr);&nbsp; &nbsp;
&nbsp; }
} 

Neste código repare que foi modificado a propriedade Table1.BorderWidth e BorderWidth de cada célula também, o resultado será:
&nbsp;
The Image Control
O controle de image como o nome ja sugere, renderiza uma imagem no browser, mais uma vez vale lembrar que só é válido usar este controle caso queira manipular em tempo de execução, caso contrário utilize a tag &lt;img&gt; do html. Aliás, o controle Image do asp.net irá renderizar uma &lt;img&gt; quando for processado.
O controle Image herda da classe WebControl e os controles ImageMap e ImageButton herdam diretamente de Image.
A propriedade primária do Image é ImageUrl que contém o caminho da imagem que será exibida no browser, mas existem mais algumas propriedades:AlternateText: Esta propriedade tem diversas funções. Quando por algum motivo a imagem não for carregada no browser, o texto que irá aparecer no lugar dela é o que for definido nesta propriedade. A maioria dos navegadores exibe o texto desta propriedade quando passa o cursor do mouse por cima da imagem, como um Tooltip. E a função que considero mais importante é que ajuda usuário com necessidade especiais de acessibilidade para navegar em sua página. Caso sua imagem tenha um link utilize esta propriedade para descrever seu link, caso seja uma imagem de conteúdo descreva a imagem com palavras chaves para facilitar motores de busca a indexar sua imagem corretamente.
ImageAlign: Esta propriedade especifica a posição da imagem em relação a outros objetos em sua página. Existem as seguintes opções: NotSet, Left, Right, Baseline, Top, Middle, Bottom, AbsBottom, AbsMiddle, ou TextTop.
DescriptionUrl: Esta propriedade é outro recurso de acessibilidade, quando for usados leitores não visuais para acessar sua página, ele irá encontrar nesta propriedade um link, tem que ser uma url, que irá direcionar para uma página com texto explicativo ou audio, explicando melhor o que é aquela imagem.
GenerateEmptyAlternateText: Definindo esta propriedade para true, quando a página for carregada e por algum motivo a imagem não seja carregada a propriedade alt do objeto &lt;img&gt; ficará: alt="". Desta forma quando for usado um leitor não visual o software irá ignorar esta imagem, entendo que ela não tem significado para a página.
A baixo um exemplo de código de como criar um controle Image em tempo de execução: protected void Page_Load(object sender, EventArgs e)
{
&nbsp; Image1.ImageUrl = "~/images/whale.jpg";
&nbsp; Image1.DescriptionUrl = "~/WhaleImageDescription.htm";
&nbsp; Image1.AlternateText = "This is a picture of a whale";
}

The ImageButton Control 


O controle de Image não possui o evento click, se você necessitar deste evento, é necessário utilizar o controle ImageButton ou ImageMap, estes controles são renderizados como o controle Image com a diferença de funcionar como um botão, com estes controles é possível também localizar as coordenadas x e y de onde o usuário clicou, caso queira tomar alguma decisão em relação a este aspecto.


O controle ImageButton é renderizado no html como: &lt;input type="image"&gt;, por ter eventos associados a ele, é possível executar um PostBack em seu formulário através do controle. Por herdar diretamente do controle Image o ImageButton possui as mesmas propriedades como AlternateText, DescriptionUrl, ImageAlign, e GenerateEmptyAlternateText.


O ImageButton assim como o Button possui dois eventos o click e o command, a diferença entre eles já explique em lições anteriores. O segundo parâmetro de ambos os eventos é do tipo ImageClickEventArgs, que é o parâmetro que possui as coordenadas do clique.


O código a seguir demonstra o clique em um ImageButton:


public partial class ImageButton_Control : System.Web.UI.Page
{
&nbsp; protected void Page_Load(object sender, EventArgs e)
&nbsp; {
&nbsp;&nbsp;&nbsp; ImageButton1.ImageUrl = "~/images/redblue.jpg";
&nbsp;&nbsp;&nbsp; ImageButton1.AlternateText =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "This is a button. The left side is red. The right is blue.";
&nbsp; }
&nbsp; protected void ImageButton1_Click(object sender, ImageClickEventArgs e)
&nbsp; {
&nbsp;&nbsp;&nbsp; ImageButton1.AlternateText =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string.Format("Button Clicked at {0},{1}", e.X, e.Y);
&nbsp; }
}


Repare que no evento Click do botão, é definida a propriedade AlternateText com os valores das coordenadas de onde o usuário clicou.


The ImageMap Control

O ImageMap é similar ao ImageButton, a grande diferença é que em qualquer lugar que clicar do ImageButton irá ocasionar o PostBack, já com o ImageMap é possível definir regiões "hot spots" que irão ocasionar o PostBack.

O ImageMap quando renderizado gera o elemento html: &lt;img usemap="#myMap"&gt;. Assim como o ImageButton o ImageMap herda diretamente da classe Image, por isso possui as mesmas propriedades.
 

No asp.net o ImageMap é representado pelo elemento: &lt;asp:ImageMap&gt; e seus elementos são: CircleHotSpot, RectangleHotSpot, e PolygonHotSpot.

Working with HotSpot Classes

O HotSpot é uma área pré-definida da imagem que quando clicada irá executar uma ação. É possível criar várias áreas dentro da mesma imagem. As classes que herdam da classe HotSpot são CircleHotSpot, RectangleHotSpot, e PolygonHotSpot. Propriedades:
AccessKey: já explicado anteriormente em outros controles;
AlternateText: já explicado anteriormente em outros controles;
HotSpotMode: Comportamento quando clicar na área (HotSpot) criada. Pode ser definido como: NotSet, Inactive, Navigate, ou PostBack;
NavigateUrl: Url que irá navegar quando a área for clicada;
PostBackValue: Uma string que será passada para o lado do servidor quando a área for clicada;
TabIndex: Número indice do HotSpot;
Target: A janela ou frame que será exibido o resultado do clique da área.
&nbsp;Understanding the HotSpotMode PropertyA propriedade HotSpotMode é usada para definir o comportamento do HotSpot quando ele for clicado. Esta propriedade pode ser definida tanto em um HotSpot como no controle ImageMap. Se você definir o valor desta propriedade para ambos, prevalecerá o valor que estiver no HotSpot e ignorará o valor atribuido ao ImageMap. Vamos aos valores permitidos desta propriedade:&nbsp;NoSet: É usado quando você quer herdar o comportamento padrão definido no controle ImageMap, você define a propriedade no ImageMap e no HotSpot deixe como NotSet;
Navigate: Simples, especifique uma url que será aberta quando clicar em seu HotSpot;
PostBack: Quando o HotSpot for clicado ele irá executar um PostBack em seu formulário enviando os dados para o servidor. Basta criar o evento e informar o valor da propriedade PostBackValue que será passada no parâmetro ImageMapEventArgs do seu evento.
Inactive: Como o nome já diz não será feito nada. Por que usar? Você pode criar HotSpot de zonas complexas, onde você define uma área inativa dentro de outro HotSpot ativo.
O código abaixo demonstra como usar, teremos uma imagem que contém 3 cores e é possível definir a região de cada cor:public partial class HotSpotControl : System.Web.UI.Page
{
&nbsp; protected void Page_Load(object sender, EventArgs e)
&nbsp; {
&nbsp;&nbsp;&nbsp; ImageMapStopLight.ImageUrl = "~/images/stoplight.jpg";&nbsp;&nbsp;&nbsp;&nbsp; ImageMapStopLight.AlternateText = "Stoplight picture";&nbsp;
 &nbsp;&nbsp;&nbsp; ImageMapStopLight.HotSpotMode = HotSpotMode.PostBack;&nbsp;&nbsp;&nbsp; &nbsp;
 &nbsp;&nbsp;&nbsp; RectangleHotSpot redHotSpot = new RectangleHotSpot();&nbsp;&nbsp;&nbsp; &nbsp;
 &nbsp;&nbsp;&nbsp; redHotSpot.Top = 0;&nbsp;&nbsp;&nbsp; &nbsp;
 &nbsp;&nbsp;&nbsp; redHotSpot.Bottom = 40;&nbsp;&nbsp;&nbsp;&nbsp;
 &nbsp;&nbsp;&nbsp;&nbsp; redHotSpot.Left = 0;&nbsp;&nbsp;&nbsp; &nbsp;
 &nbsp;&nbsp;&nbsp; redHotSpot.Right = 40;&nbsp;&nbsp;&nbsp; &nbsp;
 &nbsp;&nbsp;&nbsp; redHotSpot.PostBackValue = "RED";&nbsp;&nbsp;&nbsp;&nbsp;
 &nbsp;&nbsp;&nbsp;&nbsp; ImageMapStopLight.HotSpots.Add(redHotSpot);&nbsp;&nbsp;&nbsp;&nbsp;
 &nbsp;&nbsp;&nbsp;&nbsp; RectangleHotSpot yellowHotSpot = new RectangleHotSpot();&nbsp;&nbsp;&nbsp;&nbsp;
 &nbsp;&nbsp;&nbsp;&nbsp; yellowHotSpot.Top = 41;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; &nbsp;
 &nbsp;&nbsp;&nbsp; yellowHotSpot.Bottom = 80;&nbsp;&nbsp;&nbsp; &nbsp;
 &nbsp;&nbsp;&nbsp; yellowHotSpot.Left = 0;&nbsp;&nbsp;&nbsp; &nbsp;
 &nbsp;&nbsp;&nbsp; yellowHotSpot.Right = 40;&nbsp;&nbsp;&nbsp; &nbsp;
 &nbsp;&nbsp;&nbsp; yellowHotSpot.PostBackValue = "YELLOW";&nbsp;
 &nbsp;&nbsp;&nbsp; ImageMapStopLight.HotSpots.Add(yellowHotSpot);&nbsp;&nbsp;&nbsp;&nbsp;
 &nbsp;&nbsp;&nbsp; RectangleHotSpot greenHotSpot = new RectangleHotSpot();&nbsp;&nbsp;&nbsp;&nbsp;
 &nbsp;&nbsp;&nbsp; greenHotSpot.Top = 81;&nbsp;&nbsp;&nbsp; greenHotSpot.Bottom = 120;&nbsp;&nbsp;&nbsp; &nbsp;
 &nbsp;&nbsp;&nbsp; greenHotSpot.Left = 0;&nbsp;&nbsp;&nbsp; &nbsp;
 &nbsp;&nbsp;&nbsp; greenHotSpot.Right = 40;&nbsp;&nbsp;&nbsp; &nbsp;
 &nbsp;&nbsp;&nbsp; greenHotSpot.PostBackValue = "GREEN";&nbsp;&nbsp;&nbsp; &nbsp;
 &nbsp;&nbsp;&nbsp; ImageMapStopLight.HotSpots.Add(greenHotSpot);&nbsp; &nbsp;
 &nbsp; }
&nbsp; protected void ImageMapStopLight_Click(object sender, ImageMapEventArgs e)
&nbsp; {
&nbsp;&nbsp;&nbsp; Label1.Text = string.Format("You clicked the {0} rectangle.", e.PostBackValue);
&nbsp; }
}Resultado quando se clica no retângula verde:&nbsp;
The Calendar Control 
O controle Calendar irá exibir um calendário em sua página. Ele é usado para seleção de datas, seja um única data ou um conjunto de datas. No asp.net o elemento dele é o &lt;asp:Calendar&gt;, quando renderizado em sua página ele irá gerar uma &lt;table&gt; html associada com javascripts que o próprio asp.net irá criar.


Como eu disse o Calendar tem a opção de selecionar nenhum ou várias datas, isto é contralado pela propriedade SelectionMode, e as opções disponíveis são:
Day: permite selecionar uma data simples;
Week: permite selecionar uma data simples ou uma semana completa;
WeekMonth: permite selecionar uma data simples, uma semana completa ou todo o mês;
one: não permite que você selecionar qualquer data.
O Calendar tem uma série de propriedades que permite você ajustar seu formato:Caption: texto renderizado no calendário;
CaptionAlign: alinhamento do texto: Top, Bottom, Left, Right, ou NotSet;
CellPadding: espaço da célula para a borda da célula;
CellSpacing: espaço entra cada célula;
DayHeaderStyle: o estilo que será aplicado aos dias da semana;
DayNameFormat: o formato dos nomes dos dias das semanas: FirstLetter,
FirstTwoLetters, Full, Short, Shortest;
DayStyle: estilo padrão para os dias do calendário;
FirstDayOfWeek: o dia da semana que será exibido na primeira coluna do calendário;
NextMonthText: texto que será exibido no controle de navegação para ir para o próximo mês, por padrão o usado é &gt;. Este controle de navegação só é habilitado quando a propriedade ShowNextPrevMonth for true;
NextPrevFormat: define o formato dos controles de navegação próximo e anterior. Pode ser definido como CustomText (padrão), FullMonth(exemplo Janeiro) ou ShortMonth (exemplo Jan);
NextPrevStyle: estilo que será aplicado aos controles de navegação;
OtherMonthDayStyle: estilo dos dias do calendário e não são do mês selecionado;
PrevMonthText: texto que será exibido no controle de navegação para ir para o mês anterior, por padrão o usado é &lt;. Este controle de navegação só é habilitado quando a propriedade ShowNextPrevMonth for true;
SelectedDate: data selecionada pelo usuário;
SelectedDates: coleção de datas selecionada pelo usuário, quando assim for permitido;
SelectedDayStyle: estilo da data selecionada;
SelectionMode: valor que indica como as datas podem ser selecionadas, como ja expliquei a cima;
SelectMonthText: texto exibido para a seleção do mês, por padrão é &gt;&gt;;
SelectorStyle: estilo para os seletores de semana e mês;
SelectWeekText: texto de seleção da semana no seletor;
ShowDayHeader: indica se o header do dia deve ser exibido;
ShowGridLines: indica se deve exibir gridLines;
ShowNextPrevMonth: indica se os controles de navegação entre meses deve ser exibido;
ShowTitle: indica se o titulo deve ser exibido;
TitleFormat: indica como deve ser o formato do título, exibindo o mês ou mês e ano;
TitleStyle: estilo do título;
TodayDayStyle: estilo do dia atual;
TodaysDate: data de hoje;
UseAccessibleHeader: quando definido como true os headers do dia serão gerados como &lt;th&gt;, é o padrão, quando definido como false serão gerados &lt;td&gt;;
VisibleDate: define qual data será exibida quando o calendário for exibido;
WeekendDayStyle: estilo dos dias de final de semana.
O Calendar também possui eventos para se trabalhar. O evento primário é o SelectionChanged, ele causa um potback e é disparado no momento em que o usuário seleciona uma nova data no calendário. Dentro desta evento é possivel receber a data selecionada através da propriedade SelectedDate.Outro evento é o VisibleMonthChanged que também causa um postback e é disparado no momento em que o usuário altera o mês que esta visivel no calendário.
O calendar é tipicamente usado como um selecionador de datas, mas pode ser usado para exibir tarefas agendadas.Utilizando o evento DayRender, que é disparado no momento em que o calendário esta sendo criado e irá ser renderizado no html a cada dia do mês, você pode adicionar controles como um label junto com o dia do calendário.
O código abaixo demonstra como exibir as informações em texto de datas especiais junto com o dia no calendário.
private Dictionary&lt;DateTime, string&gt; scheduleData = new Dictionary&lt;DateTime,string&gt;(5);

protected void Page_Load(object sender, EventArgs e)
{
&nbsp; // Load the schedule (which would be read from a database)&nbsp; &nbsp;
&nbsp; scheduleData.Add(new DateTime(2011, 1, 9), "Vacation Day");&nbsp;&nbsp;
&nbsp; scheduleData.Add(new DateTime(2011, 1, 18), "Budget planning meeting");&nbsp;&nbsp;
&nbsp; scheduleData.Add(new DateTime(2011, 2, 5), "Conference call");&nbsp; &nbsp;
&nbsp; scheduleData.Add(new DateTime(2011, 2, 10), "Meet with art director");&nbsp; &nbsp;
&nbsp; scheduleData.Add(new DateTime(2011, 2, 15), "Vacation day");&nbsp; &nbsp;
&nbsp; Calendar1.Caption = "Personal Schedule";&nbsp; Calendar1.FirstDayOfWeek = FirstDayOfWeek.Sunday;&nbsp;&nbsp;
&nbsp;&nbsp; Calendar1.NextPrevFormat = NextPrevFormat.ShortMonth;&nbsp;&nbsp;
&nbsp;&nbsp; Calendar1.TitleFormat = TitleFormat.MonthYear;&nbsp; &nbsp;
&nbsp; Calendar1.ShowGridLines = true;&nbsp;&nbsp;
&nbsp; Calendar1.DayStyle.HorizontalAlign = HorizontalAlign.Left;&nbsp; &nbsp;
&nbsp; Calendar1.DayStyle.VerticalAlign = VerticalAlign.Top;&nbsp; &nbsp;
&nbsp; Calendar1.DayStyle.Height = new Unit(75);&nbsp; &nbsp;
&nbsp; Calendar1.DayStyle.Width = new Unit(100);&nbsp; &nbsp;
&nbsp; Calendar1.OtherMonthDayStyle.BackColor = System.Drawing.Color.Cornsilk;&nbsp;
&nbsp; Calendar1.TodaysDate = new DateTime(2011, 1, 1);&nbsp; &nbsp;
&nbsp; Calendar1.VisibleDate = Calendar1.TodaysDate;
}

protected void Calendar1_SelectionChanged(object sender, EventArgs e)
{&nbsp;&nbsp;
&nbsp; ActionLabel.Text = string.Format("Selection changed to: {0}", Calendar1.SelectedDate.ToShortDateString());
}

protected void Calendar1_VisibleMonthChanged(object sender, MonthChangedEventArgs e)
{&nbsp;
&nbsp; ActionLabel.Text = string.Format("Month changed to: {0}", e.NewDate.ToShortDateString());
}

protected void Calendar1_DayRender(object sender, DayRenderEventArgs e)
{&nbsp;&nbsp;
&nbsp; if (scheduleData.ContainsKey(e.Day.Date))&nbsp; &nbsp;
&nbsp; {&nbsp; &nbsp; &nbsp;
&nbsp;&nbsp;&nbsp; Literal lit = new Literal();&nbsp; &nbsp; &nbsp;
&nbsp;&nbsp;&nbsp; lit.Text = "&lt;br /&gt;";&nbsp; &nbsp; &nbsp;
&nbsp;&nbsp;&nbsp; e.Cell.Controls.Add(lit);&nbsp; &nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; Label lbl = new Label();&nbsp; &nbsp; &nbsp;
&nbsp;&nbsp;&nbsp; lbl.Text = (string)scheduleData[e.Day.Date];&nbsp; &nbsp; &nbsp;
&nbsp;&nbsp;&nbsp; lbl.Font.Size = new FontUnit(FontSize.Small);&nbsp; &nbsp; &nbsp;
&nbsp;&nbsp;&nbsp; e.Cell.Controls.Add(lbl);&nbsp; &nbsp;
&nbsp; }
}
Este código define no evento Page_Load algumas propriedades do calendário, e utiliza o evento Calendar1_DayRender para fazer a verificação se a data é uma data especiail para ser exibida. Veja o resultado:
&nbsp;
The FileUpload Control
O controle FileUpload permite ao usuário fazer o upload de arquivos para o servidor. Este controle exibe um textbox e um botão. O usuário pode informar o caminho completo do arquivo ou clicar no botão e navegar pelo browser até encontrar o arquivo desejado.
Sua tag no asp.net é &lt;asp:FileUpload&gt; quando renderizado no html ele gera um &lt;input type="file"&gt;.&nbsp;
O FileUpload não ocasiona postback de forma automática, somente é feito o postback por intervenção de outro controle como um botão de enviar/gravar ou outro.
As propriedade para acessar o arquivo são:FileBytes: Expõe o arquivo como um array de byte;
FileContent: Expõe o arquivo como stream;
PostedFile: Expõe o arquivo como objeto do tipo HttpPostedFile. Este objeto contém outras propriedades como ContentType e ContentLength.
É importante que você fala uma análisa do arquivo que esta sendo enviado para o servidor. Você pode analisar características como nome do arquivo, tamanho e tipo. Quando estiver tudo ok, utiliza o método SaveAs para completar o upload.

O tamanho máximo do arquivo que pode ser utilizado é configurado pelo atributo MaxRequestLength que fica no elemento httpRuntime no arquivo web.config. Se o usuário tentar postar algo maior do que o delimitado o upload irá falhar.&nbsp;

No exemplo a baixo foi criado uma página com um FileUpload e um botão para salvar o arquivo em uma pasta chamada Uploads:
 
protected void Button1_Click(object sender, EventArgs e)
{
&nbsp; if (FileUpload1.HasFile)
&nbsp; {
&nbsp;&nbsp;&nbsp; Label1.Text = string.Format("File Length: {0}&lt;br /&gt;File Name: {1}&lt;br /&gt;MIME Type: {2}",&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; FileUpload1.FileBytes.Length, FileUpload1.FileName, FileUpload1.PostedFile.ContentType);
&nbsp;&nbsp;&nbsp; FileUpload1.SaveAs(MapPath("~/Uploads/" + FileUpload1.FileName));
&nbsp; }
&nbsp; else
&nbsp; {
&nbsp;&nbsp;&nbsp; Label1.Text = "No file received.";
&nbsp; }
}


Como resultado, após clicar no botão submit o arquivo será salva na pasta destino e exibirá suas popriedades na label:


&nbsp;
The Panel Control
O Panel é usado como um container. Ele é útil quando você precisar agrupar um grupo de controles. O exemplo mais comum é colocar vários controles dentro dele e conseguir esconder e exibir todos alterando somente a propriedade visible do Panel.
No asp.net sua tag é &lt;asp:Panel&gt; quando renderizado no html será gerado uma &lt;div&gt;. Algumas propriedades do Panel:BackImageUrl: Usado para exibir uma imagem de fundo no Panel;
HorizontalAlignment: Define o alinhamento horizontal dos controles que estão dentro do Panel;
Wrap: Especifica se os controles que estão dentro do Panel continuam na próxima linha quando acabar o espaço da linha.
DefaultButton: Especifica o botão que será disparado quando o focu estiver no Panel e o usuário pressionar a tecla Enter.
No exemplo a seguir com o clique do botão o usuário consegue esconder um grupo de controles que estão dentro do Panel:

Código aspx:
&lt;body&gt;
&lt;form id="form1" runat="server"&gt;
&lt;div&gt;
&lt;asp:Button ID="ButtonShowHide" runat="server" Text="Login: hide form"
width="200" onclick="ButtonShowHide_Click"/&gt;
&lt;asp:Panel ID="Panel1" runat="server" BackColor="Beige" Width="200"&gt;
&lt;asp:Label ID="Label1" runat="server" Text="User name: "&gt;&lt;/asp:Label&gt;
&lt;br /&gt;
&lt;asp:TextBox ID="TextBox1" runat="server"&gt;&lt;/asp:TextBox&gt;
&lt;br /&gt;
&lt;asp:Label ID="Label2" runat="server" Text="Password: "&gt;&lt;/asp:Label&gt;
&lt;br /&gt;
&lt;asp:TextBox ID="TextBox2" runat="server"&gt;&lt;/asp:TextBox&gt;
&lt;br /&gt;
&lt;asp:Button ID="ButtonLogin" runat="server" Text="Login" /&gt;
&lt;/asp:Panel&gt;
&lt;/div&gt;
&lt;/form&gt;
&lt;/body&gt;


Código c#:
protected void ButtonShowHide_Click(object sender, EventArgs e)
{
&nbsp; Panel1.Visible = !Panel1.Visible;
&nbsp; if (Panel1.Visible)
&nbsp; {
&nbsp;&nbsp;&nbsp; ButtonShowHide.Text = "Login: hide form";
&nbsp; }
&nbsp; else
&nbsp; {
&nbsp;&nbsp;&nbsp; ButtonShowHide.Text = "Login: show form";
&nbsp; }
}

Neste exemplo clicando no botão o usuário ira alterar em esconder e exibir os controles de login.


The MultiView and View Controls
 

Assim como o Panel, os controles de MultiView e View trabalham como container para agrupar controles. A MultiView funciona como container da View, que por sua vez é o container dos demais controles. Dentro de uma MultiView podem contar várias Views. Esses controles foram criados para trabalhar juntos e não podem ser usados separadamente.

Você deve usar a propriedade ActiveViewIndex ou o método SetActiveView para definir qual View é exibida. Se o ActiveViewIndex for definido como -1, nenhum controle de View será exibido, se for passada uma View inválida ou null para o método SetActiveView uma exception será disparada. Repare que somente uma View pode estar ativa por vez.

Um exemplo útil do uso desses controles é a criação de wizards, onde por exemplo um usuário deve seguir de 3 a 4 passos para se registrar em um site. Cada passo desse registro pode estar em uma View diferente, veja na imagem:


Para gerenciar esta página foram criados command buttons para navegação. Quando o usuário clicar no botão através da propriedade CommandName do CommandEventArgs será possível identificar no evento qual botão foi clicado. Veja o código:

public partial class ViewControl : System.Web.UI.Page
{
&nbsp; protected void Page_Load(object sender, EventArgs e)
&nbsp; {
&nbsp;&nbsp;&nbsp; MultiView1.ActiveViewIndex = 0;
&nbsp; }
&nbsp; protected void Button_Command(object sender, CommandEventArgs e)
&nbsp; {
&nbsp;&nbsp;&nbsp; switch (e.CommandName)
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case "Step1Next":
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MultiView1.ActiveViewIndex = 1;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case "Step2Back":
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MultiView1.ActiveViewIndex = 0;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case "Step2Next":
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MultiView1.ActiveViewIndex = 2;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case "Step3Back":
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MultiView1.ActiveViewIndex = 1;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case "Finish":
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //hide control from user to simulate save
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MultiView1.ActiveViewIndex = -1;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;
&nbsp;&nbsp;&nbsp; }
&nbsp; }
}

Quando a página for exibida sera mostrada a primeira View para o usuário como o primeiro passo, e conforme ele for navegando as demais Views vão sendo exibidas e outras escondidas:


The Wizard Control

O controle Wizard é um controle complexo que agrega controles para que o usuário possa de forma continua inserir informações em sua webpage. O Wizard funciona de forma semelhante aos controles de MultiView e View explicados anteriormente. A idéia dele é criar um passo a passo lógico de um processo.

O que é feito com o Wizard pode muito bem ser feito com várias páginas, mas esta é a diferença principal, com o Wizard você centraliza tudo em uma unica página, facilitando o processo de desenvolvimento.
 
O Wizard possui um header para customizar com informações do passo especifico que o usuário esta naquele momento. Possui uma sidebar que irá conter os controles de navegação entre cada passa do Wizard. É possível programar qual passo é exibido, não obrigando o usuário a passar em todos os passos de forma linear caso não queira.


O que determina qual botão é exibido ou não é a propriedade StepType da classe BaseWizardStep. Os valores disponíveis são:
WizardStepType.Auto: este é o valor padrão. Os botões são renderizados com base na localização do passo dentro da coleção do Wizard;
WizardStepType.Complete: este é o passo final da coleção de passos, os botões de Final e Anterior serão exibidos;
WizardStepType.Start: este é o primeiro passo, e somente o botão de próximo irá aparecer;
WizardStepType.Step: este é um passo intermediário, os botões de Próximo e Anterior são renderizados.
No exemplo a seguir o controle de Wizard é montado para dar opção do usuário escolher alguns itens do seu veículo. Os passos criados no Wizard são: Exterior, Interior, Opcionais, and Resumo. No Exterior contem 3 RadioButtons para escolher a cor externa: vermelho, azul ou preto. No passo do Interior contém 2 RadioButton para escolher se quer banco de couro ou de pano. Nos Opcionais contém CheckBox para escolher: Rádio, Bancos Aquecidos e Ar-Condicionado. No Resumo tem uma Label que é populada com as opções escolhidas. Veja como ficou:




Após cada passo do Wizard ser criado, foi criado um código para popular a Label quando chegar ao Resumo, também foi adicionado código no evento Page_Load da página para determinar o primeiro passo do Wizard. E no evento Wizard1_FinishButtonClick foi adicionado código para exibir os resultados na label.


protected void Page_Load(object sender, EventArgs e)
{
&nbsp; if (!IsPostBack)
&nbsp; {
&nbsp;&nbsp;&nbsp; Wizard1.ActiveStepIndex = 0;
&nbsp; }
}
&nbsp;
protected void Wizard1_FinishButtonClick(object sender, WizardNavigationEventArgs e)
{
&nbsp; Wizard1.Visible = false;
&nbsp; Response.Write(string.Format("Finished&lt;br /&gt;{0}", Label1.Text));
}

protected void Wizard1_NextButtonClick(object sender, WizardNavigationEventArgs e)
{
&nbsp; if (Wizard1.WizardSteps[e.NextStepIndex].Title == "Summary")
&nbsp; {
&nbsp;&nbsp;&nbsp; StringBuilder sb = new StringBuilder();
&nbsp;&nbsp;&nbsp; foreach (WizardStep ws in Wizard1.WizardSteps)
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach (Control c in ws.Controls)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (c is CheckBox)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CheckBox cb = (CheckBox)c;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (cb.Checked)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sb.AppendFormat("{0}&lt;br /&gt;", cb.Text);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; Label1.Text = sb.ToString();
&nbsp; }
}


Quando a página for exibida, o primeiro passo será exibido ao usuário (Exterior), o usuário pode ir passo a passo ou ir direto para o passo final clicando em Finish. Quando clicar no Finish o controle de Wizard será escondido e irá aparecer o Resumo onde a Label é populada com as opções escolhidas.

The Xml Control&nbsp;

O controle Xml é utilizado para exibir o conteúdo de arquivos Xml. Este controle é bastante útil quando seus dados estão armazenados em arquivo Xml e você precisa executar uma transformação para Extensible Stylesheet Language (XSL). Os dados podem ser renderizados e exibidos para o usuário utilizando o controle Xml.

O documento Xml será exibido se especificada a propriedade DocumentSource ou a propriedade DocumentContent. A propriedade DocumentSource aceita uma string que contém o caminho do arquivo Xml a ser carregado. A propriedade DocumentContent aceita uma string com o conteúdo do Xml.

A propriedade TransformSource aceita um parâmetro opcional que contém o caminho de um arquivo XSL que será aplicado ao Xml. Esta propriedade também aceita um objeto do tipo Transform. O controle Xml contém a propriedade TransformArgumentList que aceita parâmetros que serão passados para a transformação XSL.


No código a seguir o controle Xml é utilizado para exibid o contéudo de um arquivo Xml após uma transformação XSL é aplicada. A seguir o arquivo Xml e o arquivo XSL:


Arquivo XML: ProductList.xml
&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;ProductList&gt;
&lt;Product Id="1A59B" Department="Sporting Goods" Name="Baseball" Price="3.00" /&gt;
&lt;Product Id="9B25T" Department="Sporting Goods" Name="Tennis Racket" Price="40.00" /&gt;
&lt;Product Id="3H13R" Department="Sporting Goods" Name="Golf Clubs" Price="179.00" /&gt;
&lt;Product Id="7D67A" Department="Clothing" Name="Shirt" Price="12.00" /&gt;
&lt;Product Id="4T21N" Department="Clothing" Name="Jacket" Price="45.00" /&gt;
&lt;/ProductList&gt;


Arquivo XSL: ProductList.xsl
&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:labs="http://labs.com/mynamespace"&gt;
&lt;xsl:template match="/"&gt;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Product List&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;center&gt;
&lt;h1&gt;Product List&lt;/h1&gt;
&lt;xsl:call-template name="CreateHeading"/&gt;
&lt;/center&gt;
&lt;/body&gt;
&lt;/html&gt;
&lt;/xsl:template&gt;
&lt;xsl:template name="CreateHeading"&gt;
&lt;table border="1" cellpadding="5"&gt;
&lt;tr &gt;
&lt;th bgcolor="yellow"&gt;
&lt;font size="4" &gt;
&lt;b&gt;Id&lt;/b&gt;
&lt;/font&gt;
&lt;/th&gt;
&lt;th bgcolor="yellow"&gt;
&lt;font size="4" &gt;
&lt;b&gt;Department&lt;/b&gt;
&lt;/font&gt;
&lt;/th&gt;
&lt;th bgcolor="yellow"&gt;
&lt;font size="4" &gt;
&lt;b&gt;Name&lt;/b&gt;
&lt;/font&gt;
&lt;/th&gt;
&lt;th bgcolor="yellow"&gt;
&lt;font size="4" &gt;
&lt;b&gt;Price&lt;/b&gt;
&lt;/font&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;xsl:call-template name="CreateTable"/&gt;
&lt;/table&gt;
&lt;/xsl:template&gt;
&lt;xsl:template name="CreateTable"&gt;
&lt;xsl:for-each select="/ProductList/Product"&gt;
&lt;tr&gt;
&lt;td align="center"&gt;
&lt;xsl:value-of select="@Id"/&gt;
&lt;/td&gt;
&lt;td align="center"&gt;
&lt;xsl:value-of select="@Department"/&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;xsl:value-of select="@Name"/&gt;
&lt;/td&gt;
&lt;td align="right"&gt;
&lt;xsl:value-of select="format-number(@Price,'$#,##0.00')"/&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/xsl:for-each&gt;
&lt;/xsl:template&gt;
&lt;/xsl:stylesheet&gt;


Para exibir o resultado foi adicionado um controle Xml na página e o código a seguir:


public partial class XmlControlVb : System.Web.UI.Page
{
&nbsp; protected void Page_Load(object sender, EventArgs e)
&nbsp; {
&nbsp;&nbsp;&nbsp; Xml1.DocumentSource = "~/App_Data/ProductList.xml";
&nbsp;&nbsp;&nbsp; Xml1.TransformSource = "~/App_Data/ProductList.xsl";
&nbsp; }
}


Quando a página é exibida os arquivos são carregados e o resultado:




Com o controle Xml encerra o capítulo 4!!