c # .net ListView - получить различную информацию из разных таблиц

2

Im, используя С#.net.

Я смотрю вокруг Интернета и не могу найти что-нибудь, что поможет мне.

У меня есть список подрядчиков, ежедневные часы, ежедневные слоты (три разные таблицы).

  • Первая строка - содержит подрядчиков имена.
  • Вторая строка - неограниченная - содержит слоты.

Например

Изображение 174551

Я думал, что могу использовать ListView, но у меня возникли проблемы с разработкой места, где я бы разместил код.

    <asp:ListView ID="contractorListView" runat="server">
    <LayoutTemplate>
  <table runat="server">
   <tr>
    <td>Times</td>  
    // Contractors names pulled from another
    <th><asp:PlaceHolder id="itemPlaceholder" runat="server" /></th>
      </tr>
    </LayoutTemplate>
  <ItemTemplate>
   <tr>
    <td>Times pulled from one database table</td>
    <td align="left" style="width: 200px;">
     // Customers name - attached to correct time
     <asp:Label runat="server" Text='<%#Eval("person_name")%>' />
    </td> 
   </tr>
     </ItemTemplate>
    </asp:ListView>

Использует модель Linq, поэтому может подключаться к интервалу времени клиента

            ObjectDataSource contractorDataSource = new ObjectDataSource();
            contractorDataSource.SelectMethod = "GetContractorByDateCategory";
            contractorDataSource.TypeName = "contractBook.classes.contractorRepository";

            contractorListView.DataSource = contractorDataSource;

            contractorDataSource.DataBind();
            contractorListView.DataBind();

У кого-нибудь есть идеи/пример?

Заранее благодарим за помощь.

Clare

  • 0
    Я не совсем понимаю вашу проблему. У вас есть ваши данные? Вы знаете, как разместить его в ListView ? И что вы подразумеваете под тем, где его разместить? Везде, где вы хотите, чтобы ListView был.
Теги:
data-binding
listview

3 ответа

4
Лучший ответ

Вот как я обычно решаю такие проблемы:

  • вручную вытащите наши данные, которые вы хотите показать (вызывая методы репозитория, не используя ObjectDataSource для этого). Для эффективности часто имеет смысл сделать один большой запрос, который возвращает денормализованные записи, каждый из которых содержит все столбцы, которые вам понадобятся (например, SELECT TimeSlot, CustomerName, ContractorName FROM (joins go here) ...)

  • создать пользовательский класс коллекции, который помещает эти данные в формат, который легко связывается с данными. "Простое связывание данных" обычно означает, что данные организованы в том же порядке, который вы собираетесь отображать. Вам также может понадобиться делать взломы, например, делая все ваши строки одинаковой длины, чтобы привязывать данные к тому же количеству ячеек таблицы в строке.

  • в ваших выражениях привязки данных, приведите Container.DataItem к любому типу, который вам нужен, чтобы вытащить свойства этого типа. Это также имеет дополнительное преимущество, заключающееся в том, что при создании компиляции с ошибками привязки данных с опечатками возникают сбои, а не ожидая, пока среда выполнения не найдет ошибки.

  • для вложенности задайте свойство DataSource вложенного элемента управления шаблона (например, повторителя) для свойства родительского контейнера. DataTemet

  • для строк заголовка, вот трюк: поместите код заголовка непосредственно в ItemTemplate и используйте Container.ItemIndex == 0, чтобы знать, когда показывать строку заголовка или нет. Поскольку только Repeater (но не ListView) поддерживает свойство ItemIndex, я стараюсь использовать Repeater вместо ListView для большинства задач привязки данных только для чтения. Вот почему я изменил свой ListView в моем примере кода ниже, чтобы использовать Repeater. То же самое можно сделать, добавив свойство Index или RowNumber в свои настраиваемые классы привязки данных, описанные выше, но это сложнее.

Общая идея заключается в том, что вы хотите максимально эффективно использовать свой интеллект из своего кода привязки данных и к фактическим методам кода вашей страницы (или кода), который легче писать и отлаживать.

Здесь рабочий образец (с вашими классами и репозиториальными классами), чтобы дать вам представление о том, о чем я говорю. Вы должны уметь адаптировать это к своей ситуации.

<%@ Page Language="C#"%>
<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="System.Linq" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
    public class Person   // replace with your class
    {
        public string person_name {get; set;}
    }
    public class Repository  // replace with your class
    {
        public static IEnumerable<Record> GetCustomerByDateCategory()
        {
            // fake some data
            return new Record[] 
            {
                new Record { Time = new DateTime(2000, 1, 1, 8, 0, 0), Contractor = new Person {person_name = "Joe the Plumber"},  Customer = new Person {person_name = "Joe Smith"} },
                new Record { Time = new DateTime(2000, 1, 1, 8, 30, 0), Contractor = new Person {person_name = "Bob Vila"}, Customer = new Person {person_name = "Frank Johnson"} },
                new Record { Time = new DateTime(2000, 1, 1, 8, 30, 0), Contractor = new Person {person_name = "Mr. Clean"}, Customer = new Person  {person_name = "Elliott P. Ness"} },
            };
        }
        public class Record    // replace this class with your record class
        {
            public DateTime Time {get; set;}
            public Person Contractor { get; set; }
            public Person Customer { get; set; }
        }
    }

    // key = time, value = ordered (by contractor) list of customers in that time slot
    public class CustomersByTime : SortedDictionary<DateTime, List<Person>>
    {
        public List<Person> Contractors { get; set; }

        public CustomersByTime (IEnumerable <Repository.Record> records)
        {
            Contractors = new List<Person>();
            foreach (Repository.Record record in records)
            {
                int contractorIndex = Contractors.FindIndex(p => p.person_name == record.Contractor.person_name);
                if (contractorIndex == -1)
                {
                    Contractors.Add(record.Contractor);
                    contractorIndex = Contractors.Count - 1;
                }
                List<Person> customerList;
                if (!this.TryGetValue(record.Time, out customerList))
                {
                    customerList = new List<Person>();
                    this.Add(record.Time, customerList);
                }
                while (customerList.Count < contractorIndex)
                    customerList.Add (null);    // fill in blanks if needed
                customerList.Add (record.Customer);    // fill in blanks if needed
            }
            MakeSameLength();
        }
        // extend each list to match the longest one. makes databinding easier.
        public void MakeSameLength()
        {
            int max = 0;
            foreach (var value in this.Values)
            {
                if (value.Count > max)
                    max = value.Count;
            }
            foreach (var value in this.Values)
            {
                while (value.Count < max)
                    value.Add(null);
            }
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        CustomersByTime Customers = new CustomersByTime(Repository.GetCustomerByDateCategory());
        CustomerListView.DataSource = Customers;
        CustomerListView.DataBind();
    }
</script> 
<html>
<head>
<style type="text/css">
    td, th, table { border:solid 1px black; border-collapse:collapse;}
</style>
</head>
<body>
  <asp:Repeater ID="CustomerListView" runat="server">
    <HeaderTemplate><table cellpadding="2" cellspacing="2"></HeaderTemplate>
    <ItemTemplate>
        <asp:Repeater runat="server" visible="<%#Container.ItemIndex==0 %>"
            DataSource="<%#((CustomersByTime)(CustomerListView.DataSource)).Contractors %>" >
          <HeaderTemplate>
            <tr>
               <th>Times</th>
           </HeaderTemplate>
          <ItemTemplate>
            <th><%#((Person)Container.DataItem).person_name %></th>
          </ItemTemplate>
          <FooterTemplate>            
            </tr>
          </FooterTemplate>
        </asp:Repeater>
      <tr>
        <td><%#((KeyValuePair<DateTime, List<Person>>)(Container.DataItem)).Key.ToShortTimeString() %></td>
        <asp:Repeater ID="Repeater1" runat="server" DataSource="<%# ((KeyValuePair<DateTime, List<Person>>)(Container.DataItem)).Value %>">
          <ItemTemplate>
            <td align="left" style="width: 200px;">
              <%#Container.DataItem == null ? "" : ((Person)(Container.DataItem)).person_name%>
            </td> 
          </ItemTemplate>
        </asp:Repeater>
      </tr>
    </ItemTemplate>
    <FooterTemplate></table></FooterTemplate>
  </asp:Repeater>
</body>
</html>

Кстати, если вы создаете совершенно новое приложение и имеете некоторое время для обучения, я определенно предлагаю посмотреть ASP.NET MVC, который имеет нетривиальную кривую обучения, но облегчает многое... в partiuclar такого рода сложный рендеринг данных.

  • 0
    +1 за рекомендацию ASP.NET MVC! :-)
0

Почему бы не создать один запрос, который извлекает всю вашу информацию?

Вы можете выполнить операцию JOIN по нескольким таблицам.

Если соединение становится очень сложным, вы можете создать VIEW, который создает новую виртуальную таблицу для консолидации вашей информации.

0

Это не просто ситуация с перекрестными языками? Посмотрите на мое решение здесь:

Перекрестная вкладка - сохранение разных дат (Meeting1, Meeting2, Meeting 3 и т.д.) в том же столбце

Ещё вопросы

Сообщество Overcoder
Наверх
Меню