15/09/2009

GridView oraz puste źródło danych

Home

Programistom używającym kontrolki GridView na co dzień znany jest zapewne fakt, że w przypadku pustego źródła danych kontrolka nie generuje żadnego widocznego markup'u. W szczególności nie będą widoczne nagłówki kolumn czy wiersz dodający.

Kiedy w wyszukiwarce wpiszemy hasło Show GridView if datasource is empty otrzymamy oczywiście mnóstwo rozwiązań tego problemu. Niestety pośród nich nie znajdziemy, a przynajmniej ja nie znalazłem, satysfakcjonującej odpowiedzi dotyczącej źródła danych typu ObjectDataSource. Nie będziemy natomiast osamotnienie jeśli używamy SqlDataSource. Ale co jeśli nie chcemy, nie możemy lub najzwyczajniej w świecie nie chce nam się zmieniać używanego typu źródła danych. Ja zastosowałem rozwiązanie, które opisałem poniżej.

Dla ustalenia uwagi załóżmy, że metoda dostarczająca danych wygląda następująco:
public static IEnumerable GetData()
{
  return _data;
}
Zacznijmy od zmodyfikowania tej metody w ten sposób aby zawsze zwróciła niepustą kolekcję:
public static IEnumerable GetData()
{
  if(_data.Count == 0)
  {
    _data.Add(new TestClass());
  }
  
  return _data;
}
Oczywiście teraz wszystko zadziała z wyjątkiem tego, że na kontrolce pojawi się jakiś "dziwny", sztuczny obiekt. Można temu jednak zaradzić zmieniając lekko definicję TestClass:
public class TestClass
{
  ...
  public bool IsFake
  {
    get; set;
  }
  ...
}
Przy okazji zmodyfikujemy ponownie metodę GetData:
public static IEnumerable GetData()
{
  if(_data.Count == 0)
  {
    _data.Add(new TestClass() { IsFake = true; });
  }
  
  return _data;
}
Ostatni element rozwiązania do podczepienie się pod zdarzenie OnRowDataBound kontrolki GridView w celu sterowania widocznością wierszy:
protected void GridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
  TestClass ts = e.Row.DataItem as TestClass;
  if(ts != null && ts.IsFake)
  {
    e.Row.Visible = false;
  }
}
Rozwiązanie można jeszcze rozszerzyć o usunięcie sztucznego obiektu z kolekcji w momencie kiedy pojawią się "prawdziwe" dane ale moim zdaniem nie jest to konieczne.

4 comments:

Anonymous said...

a nie lepiej uzyc GridView..::.EmptyDataTemplate Property?

Michał Komorowski said...

Powiem tak. W moim przypadku GridView miał 10 kolumn. Do zdefiniowania każdej kolumny użyłem TemplateField, a więc użycie właściwości EmptyDataTemplate wymagałoby ode mnie powtórzenia całkiem sporej ilość kodu (ItemTemplate, EditItemTemplate, FooterTemplate). Rozwiązanie jakie zaproponowałem jest mniej pracochłonne.

Kokodzambo said...

Witam. A czy da sie w samym EmptyDataTemplate wyswietlic przycisk Inserta?

Michał Komorowski said...

Jak najbardziej można np.:

<asp:GridView ID="Grid" runat="server">
   <EmptyDataTemplate>
      <asp:Button ID="InsertButton" runat="server" Text="Insert" onclick="InsertButton_Click" />
   </EmptyDataTemplate>
</asp:GridView>

Post a Comment