#c# #silverlight #silverlight-4.0 #wcf-ria-services
#c# #silverlight #silverlight-4.0 #wcf-ria-services
Вопрос:
У меня есть следующая модель данных:
Camp -> CampEvent <- Событие.
У Camp есть CampId и имя, связанное с ним. Событие имеет идентификатор события, имя, начало / конец (даты). CampEvent имеет (CampId,EventID)PK, CampId FK, EventID FK.
Таблицы используются для создания модели домена и службы домена, которая используется на стороне клиента в Silverlight.
Я успешно могу отобразить таблицу событий в Silverlight, используя сетку.
В сетке есть два столбца шаблона — один для отображения флажка, а другой для отображения названия события.
Итак, теперь проблема в том, что мне каким-то образом нужно устанавливать флажки, когда этот элемент управления переходит в режим редактирования.
Я заметил, что у сетки нет события OnDataBound, или у нее нет способа установить состояние каждого флажка на checked, кроме как через привязку.
Ответ №1:
Ну, по-видимому, в Silverlight у вас нет роскоши возиться с содержимым GridViewRow. Однако вы можете добиться этого, изменив базовый источник данных.
В приведенном выше сценарии у нас есть элемент управления, который используется для создания экземпляра Camp и связывания его с одним или многими событиями. В некотором смысле элемент управления может либо создавать, либо обновлять объект «Camp» и его связи с событиями. Состояние элемента управления контролируется перечислением public enum Mode { Create, Update };
и в зависимости от того, какое значение имеет это свойство, элемент управления будет выполнять либо одну, либо обе из следующих операций привязки:
- Получить все данные о событиях и отобразить их в сетке, состоящей из строк, имеющих флажок и метку.
- Установите флажки, обозначающие события, в которых участвует конкретный лагерь.
Теоретически все это было красиво, но в принципе я понял, что Silverlight нужен дискретный источник данных для привязки. Я создал коллекцию пользовательского объекта CampEvent, в котором у каждого элемента проверено логическое свойство, а также имя события и идентификатор события. Объект CampEvent не является объектом сущности домена и используется только для привязки.
Итак, для достижения моей цели я предпринял следующие шаги.
-
Объявите ObservableCollection, где T используется только для привязки. В этом случае базовым источником данных для T является наше событие, а запрос Linq to Entity использовался для получения идентификатора и имени события и преобразования его в объект CampEvent с его свойством IsChecked, для которого по умолчанию установлено значение false.
-
Если элемент управления находится в режиме создания, я закончил. Флажки в столбце шаблона сетки двусторонне привязаны к свойству IsChecked базового источника данных. Первого шага достаточно, чтобы создать пользовательский интерфейс по умолчанию со снятыми флажками. В противном случае перейдите к 3
-
Ну, номер 2 был неправильным, поэтому элемент управления находился в режиме «Обновления». Если свойство SelectedCamp элемента управления установлено (и это свойство имеет тип Camp). На этом этапе мы создаем запрос Linq к объектам, в котором мы просим доменную службу включить события, связанные с указанным лагерем.
-
Как только приходит ответ от запроса, мы выполняем итерацию по каждому объекту события, который связан с camp. Для каждого полученного события мы проверяем, существует ли оно в нашем источнике данных ObservableCollection. Если это происходит, мы устанавливаем для свойства IsChecked значение true для этого элемента. Как только мы привяжем сетку к данным, все события, связанные с конкретным лагерем, будут «проверены».
-
Миссия выполнена.
Несколько слов о структуре базы данных, моделях предметной области, сгенерированных Entity Framework, и WCF RIA.
Что ж, как оказалось, EF предоставит вам, возможно, 80% из коробки. Инструмент недостаточно умен, чтобы знать, что такое отношение «многие ко многим». В случае с camp и events мы имеем следующую структуру:
camp -> participates in many -> events
(many) events -> have many -> camps (as participants)
Итак, чтобы это произошло, нам нужна таблица «joiner» между лагерями и событиями. Чтобы сделать это правильно, в таблице joiner теоретически должно быть как минимум два столбца:
CampId -> EventID внешнего ключа -> Внешний ключ
Теперь, чтобы создать первичный ключ для таблицы, мы должны иметь:
CampId EventID -> Составной первичный ключ.
Создание нашей таблицы, содержащей только 2 поля. Теперь это очень важно, потому что эта связь создает свойство навигации, возможное в EF.
При создании модели предметной области EF не создаст объединяющую таблицу в модели. Однако, чтобы включить свойство навигации между Camp и Event и наоборот, есть пара вещей, которые должны произойти в базовом объекте метаданных службы домена.
** 1. Найдите информацию о метаданных лагеря. Украсьте IEnumerble<Event>Events
свойство:
[Include]
[Association("CampEvent", "CampId", "EventId", IsForeignKey=True)]
И объяснить, что это значит: В Include говорится, что всякий раз, когда вы запрашиваете модель предметной области, пожалуйста, включайте каждое событие для указанного лагеря (ов). В ассоциации говорится, что существует таблица ассоциаций между camp и event для работы свойства навигации. В таблице поиска у camp есть идентификатор CampId, а у события есть EventID. Используйте их, чтобы найти все события для указанного лагеря (ов) **.
2. Сделайте то же самое для любых других навигационных свойств, которые у вас есть.