Správce souborů pomocí DataGridu v ASP.NET – upload souborů

17. června 2004

Pomocí vykazovacích prvků DataGrid nebo Datalist můžeme snadno dát uživatelům k dispozici webové rozhraní pro soubory na serveru. V tomto článku si ukážeme, jak obsluhovat události v Datagridu, jak jeho prostřednictvím nahrávat nové soubory na server a jak stávající soubory přejmenovávat.

Na DataGrid máme navázany obsluhy různých událostí, což je důležité, pokud po DataGridu chceme více než jen prosté vysypání dat do stránky (v takovém případě by se navíc mnohem lépe hodil Repeater). Následují tedy metody zajišťující stránkování DataGridPage(), změnu počtu řádků SetPageSize(), nastavení výrazu pro vyhledávání SearchDataGrid(), přepnutí do editačního režimu DataGridEdit() a jeho stornování DataGridCancel(), zpracování příkazů (uložení, smazání) DataGridCommand() a také doplnění výsledné tabulky o změnu barvy řádku při přejetí myší obslužnou metodou DataGridItemDataBound().

Většina těchto metod neprovádí nic světoborného, víceméně tvoří „bižuterii“ – aby nám například DataGrid nezůstával přepnutý do editačního režimu nebo aby nedošlo k chybě, pokud bude třeba uživatel na stránce 30 a náhle zvýší počet řádků natolik, že se data vejdou na 10 stránek. Pokud bychom při změně velikosti stránky nenastavili aktuální stránku CurrentPageIndex na 0, dozajista by při popisované situaci došlo k výjimce.

void SetPageSize(Object sender, EventArgs e)
{
  Datagrid1.EditItemIndex = -1;
  Datagrid1.ShowFooter = true;
  Datagrid1.CurrentPageIndex = 0;
  BindDataGrid();
}
void DataGridPage (Object sender, DataGridPageChangedEventArgs e)
{
  Datagrid1.EditItemIndex = -1;
  Datagrid1.ShowFooter = true;
  Datagrid1.CurrentPageIndex = e.NewPageIndex;
  BindDataGrid();
}
void SearchDataGrid(object sender, CommandEventArgs e)
{
  switch(e.CommandName)
  {
    case „all“:
      txbSearch.Text = String.Empty;
      ViewState[„CharArgument“] = null;
    break;
    case „phrase“:
      ViewState[„CharArgument“] = null;
    break;
    case „char“:
      ViewState[„CharArgument“] = (String)e.CommandArgument;
      txbSearch.Text = String.Empty;
    break;
    default:
    break;
  }
  Datagrid1.EditItemIndex = -1;
  Datagrid1.ShowFooter = true;
  Datagrid1.CurrentPageIndex = 0;
  BindDataGrid();
}
void DataGridItemDataBound(Object sender, DataGridItemEventArgs e)
{
  if (e.Item.ItemType == ListItemType.Item)
  {
    e.Item.Attributes.Add(„onmouseover“, „javascript: this.style.backgroundColor=’#FFDDE7′;“);
    e.Item.Attributes.Add(„onmouseout“, „javascript: this.style.backgroundColor=’#FFFFFF‘;“);
  }
  if (e.Item.ItemType == ListItemType.AlternatingItem)
  {
    e.Item.Attributes.Add(„onmouseover“, „javascript: this.style.backgroundColor=’#FFDDE7′;“);
    e.Item.Attributes.Add(„onmouseout“, „javascript: this.style.backgroundColor=’#E7E7E7′;“);
  }
}
void DataGridEdit(Object sender, DataGridCommandEventArgs e)
{
  Datagrid1.EditItemIndex = e.Item.ItemIndex;
  Datagrid1.ShowFooter = false;
  BindDataGrid();
}
void DataGridCancel(Object sender, DataGridCommandEventArgs e)
{
  Datagrid1.EditItemIndex = -1;
  Datagrid1.ShowFooter = true;
  BindDataGrid();
}
void DataGridCommand(Object sender, DataGridCommandEventArgs e)
{
// přetypujeme předanou hodnotu argumentu e.CommandSource na LinkButton a rozhodneme podle vlastnosti CommandName
  switch(((LinkButton)e.CommandSource).CommandName)
  {
    case „Delete“:
      ItemDelete(e);
    break;
    case „Insert“:
      ItemInsert(e);
    break;
    default:
    break;
  }
}

Výše uvedené metody, myslím, nevyžadují detailní popis, vše by mělo být jasné z kódu. Za zmínku snad stojí rozhodnutí o prováděném povelu pomocí switch-case, kde požadovaný povel získáme přetypováním vlastnosti CommandSource vstupního parametru typu DataGridCommandEventArgs.

Smazání záznamu provede metoda ItemDelete():

void ItemDelete(DataGridCommandEventArgs e)
{
// ošetřit výjimky
  try
  {
// cesta a jméno souboru z kolekce DataKeys
    String myMediaPath = xmlDirectory + Datagrid1.DataKeys[e.Item.ItemIndex];
// pokud soubor existuje, provést smazání metodou Delete() a zneviditelnit chybové hlášení
    if (File.Exists(myMediaPath))
    { // pokud
      File.Delete(myMediaPath);
      lblError.Visible = false;
    }
// soubor neexistuje nebo k zadané cestě není přístup, zviditelníme hlášení
    else
      lblError.Visible = true;
  }
// došlo k nějaké chybě, zviditelníme hlášení
  catch
  {
    lblError.Visible = true;
  }
  lblError.Text = „Chyba při mazání souboru – soubor již možná neexistuje…“;
// pokud není chybové hlášení viditelné, nedošlo k chybě – nastavíme DataGrid do „základního“ nastavení a naplníme čerstvými daty
  if (!lblError.Visible)
  {
    Datagrid1.EditItemIndex = -1;
    Datagrid1.CurrentPageIndex = 0;
    Datagrid1.ShowFooter = true;
    BindDataGrid();
  }
}

Velmi podobná je metoda zajišťující přejmenování souboru, v níž navíc musíme vyřešit získání hodnoty textového pole, které není jednoduše přístupné, protože je skryto uvnitř šablony DataGridu. Vzniká totiž za běhu a to pouze tehdy, je-li DataGrid, respektive některý jeho řádek, v editačním režimu – jinak vůbec neexistuje. Pro dohledání prvku bychom mohli použít metodu FindControl(), ale zde můžeme prvek i „dopočítat“, což je rychlejší. Pokud by někdo raději použil FindControl(), může postupovat obdobně jako u níže popsané metody pro přidávání nových záznamů, kde jsou prvky v šabloně zápatí.

void DataGridUpdate(Object sender, DataGridCommandEventArgs e)
{
// provedeme jen když neprotestují validátory
  if (Page.IsValid)
  {
// ošetřit výjimky
    try
    {
// získat přístup k objektu textového pole v šabloně – přetypujeme objekt v daném sloupci (buňce)
      TextBox txtFileName = (TextBox) e.Item.Cells[0].Controls[1];
// pokud není zadané jméno souboru odlišné od stávajího, nebudeme přejmenování provádět
      if (txtFileName.Text != Datagrid1.DataKeys[e.Item.ItemIndex])
// metodou Move() přesuneme/přejmenujeme soubor do nového místa (na nový název)
        File.Move(xmlDirectory+Datagrid1.DataKeys[e.Item.ItemIndex],xmlDirectory+txtFileName.Text);
// skryjeme chybové hlášení
      lblError.Visible = false;
    }
    catch (Exception eX)
    {
// došlo k nějaké chybě, nastavíme text hlášení a zviditelníme je
      lblError.Text = „Soubor se nezdařilo přejmenovat, možná je používán jinou aplikací…<br />“+eX.ToString();
      lblError.Visible = true;
    }
  }
// pokud není chybové hlášení viditelné, nedošlo k chybě – nastavíme DataGrid do „základního“ nastavení a naplníme čerstvými daty
  if (!lblError.Visible)
  {
    Datagrid1.EditItemIndex = -1;
    Datagrid1.ShowFooter = true;
    BindDataGrid();
  }
}

Na závěr jsem si nechal nejdůležitější metodu – ta zajišťuje upload souboru od klienta na server.

void ItemInsert(DataGridCommandEventArgs e)
{
// provedeme jen když neprotestují validátory
  if (Page.IsValid)
  {
// ošetříme výjimky
    try
    {
// v šabloně dohledáme HtmlInputFile přetypováním dohledaného prvku v kolekci Item předaného parametru typu DataGridCommandEventArgs
      HtmlInputFile myFile = (HtmlInputFile) e.Item.FindControl(„myFile“);
// provedeme pouze pokud je nějaký soubor zadaný a byl doručen nenulový obsah
      if (myFile.PostedFile != null && myFile.PostedFile.ContentLength > 0 )
      {
// původní jméno souboru s cestou
        String fname = myFile.PostedFile.FileName;
// uložit do zadané cesty s původním názvem (původní cestu odřízneme)
        myFile.PostedFile.SaveAs(xmlDirectory + fname.Substring(fname.LastIndexOf(„\\“)+1));
// skrýt chybové hlášení
        lblError.Visible = false;
      }
      else
      {
// soubor na server nedorazil, nebo má nulovou délku, zviditelníme hlášení
        lblError.Visible = true;
        lblError.Text = „Soubor nebyl zadán nebo není správného typu.<br />“;
      }
    }
    catch (Exception eX)
    {
// došlo k nějaké chybě, zviditelníme hlášení
      lblError.Visible = true;
      lblError.Text = „Došlo k chybě při ukládání dat…<br />“;
    }
  }
// pokud není chybové hlášení viditelné, nedošlo k chybě – nastavíme DataGrid do „základního“ nastavení a naplníme čerstvými daty
  if (!lblError.Visible)
  {
    Datagrid1.EditItemIndex = -1;
    Datagrid1.ShowFooter = true;
    BindDataGrid();
  }
}

Zde chci jen připomenout statickou hodnotu ValidFileExpressionpředchozího článku, která připravuje řetězec regulárního výrazu pro validátory v DataGridu. V šabloně máme použity dva, jeden v editační šabloně a jeden v zápatí. Hodnotu ValidationExpression zde bindujeme výrazem ValidationExpression='<%# ValidFileExpression %>‘, u validátoru v zápatí si také všimněte bindování povolení validátoru v závislosti na viditelnosti zápatí Enabled='<%# Datagrid1.ShowFooter %>‘. Pokud by validátor (zejména RequiredFieldValidator) v zápatí zůstal povolen, bylo by problematické uložit údaje z editační šablony – validátory by zde protestovaly kvůli polím v zápatí, které nás však při editaci vůbec nezajímají. Po ukončení editace je zápatí opět zviditelněno a tím se povolí i validátory v něm definované.

Pro zobrazení rozměrů obrázků nám poslouží metody IsImage() a ImageSize(). První metoda nám poslouží také k vygenerování odkazu pro náhled obrázku při přejetí myší – zde v závislosti na tom, zda jde o obrázek, generujeme odlišné hodnoty atributů onmouseout a onmouseover metodou LinkPreview().

Boolean IsImage(String fileName)
{
// v zadaném řetězci najdeme pozici poslední tečky
  Int32 myExtIndex = fileName.LastIndexOf(„.“);
  if (myExtIndex > -1)
  {
// pokud byla tečka nalezena, vyjmeme část řetězce od tečky do konce převedenou na malé znaky jako příponu
    String myExtension = fileName.Substring(myExtIndex+1).ToLower();
    if (myExtension == „jpg“ || myExtension == „jpeg“ || myExtension == „gif“ || myExtension == „gif“ || myExtension == „png“ || myExtension == „tif“ || myExtension == „bmp“ || myExtension == „ico“)
// pokud se přípona rovná některé z vyjmenovaných, jde o obrázek
      return true;
    else
// jinak jde o soubor jiného typu
      return false;
  }
  else
// zadané jméno souboru neobsahuje tečku, je bez přípony, není to obrázek
    return false;
}
String ImageSize(String fileName)
{
  if (IsImage(fileName))
  {
    System.Drawing.Bitmap objBMP;
    objBMP = new Bitmap(xmlDirectory + fileName, false);
    try
    {
      return “ (“ + objBMP.Width.ToString() + „x“ + objBMP.Height.ToString() + „)“;
    }
    catch
    {
      return string.Empty;
    }
  }
  else
    return String.Empty;
}

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Další článek erinel
Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *