У меня есть проект страниц Razor, который пытается заполнить Kendo TreeView (или любой другой TreeView) из базы данных, созданной с помощью модели данных.
Страница, над которой я работаю, содержит приложения, которые используютсяи дерево читает список организаций, ссылающихся на себя, чтобы мы знали, к каким приложениям имеет доступ каждая организация или отдел и т. д.Я работаю над страницей «Изменить» в бритвенном приложении, поэтому ~ Pages \ Apps \ Edit.cshtml и ~ Pages \ Apps \ Edit.cshtml.cs со связанными страницами модели, как показано ниже.Это участвующие модели, игнорируйте RoleApps для этой проблемы:
namespace FliveRetry.Models
{
public class Org
{
public int ID { get; set; }
public string OrgName { get; set; }
public int? ParentID { get; set; }
public bool? HasChildren { get; set; }
}
}
и
namespace FliveRetry.Models
{
public class App
{
public int ID { get; set; }
public string AppName { get; set; }
public string AppDescription { get; set; }
public int? DisplayOrder { get; set; }
public bool? Archived { get; set; }
public DateTime? Saved { get; set; }
public int? SavedBy { get; set; }
public ICollection<OrgAppJoin> OrgAppJoins { get; set; }
public ICollection<RoleAppJoin> RoleAppJoins { get; set; }
}
}
и модель индекса:
{
public class AppIndexData
{
public IEnumerable<App> Apps { get; set; }
public IEnumerable<Role> Roles { get; set; }
public IEnumerable<Org> Orgs { get; set; }
public IEnumerable<RoleAppJoin> RoleAppJoins { get; set; }
public IEnumerable<OrgAppJoin> OrgAppJoins { get; set; }
}
public class AssignedAppOrgData
{
public int OrgID { get; set; }
public string Org { get; set; }
public int? ParentID { get; set; }
public bool Assigned { get; set; }
public bool? HasChildren { get; set; }
}
public class SelectedAppOrgs
{
public int OrgID { get; set; }
}
public class SelectedAppOrgNames
{
public string OrgName { get; set; }
}
У меня есть модель страницызаполнить выбранные элементы в списки с именем selectedOrgs или selectedOrgNames, которые я могу использовать в представлении.
public class AppSelectPageModel : PageModel
{
//Load list for Selecting Orgs for Apps
public List<AssignedAppOrgData> AssignedAppOrgDataList;
public List<SelectedAppOrgs> selectedOrgs;
public List<SelectedAppOrgNames> selectedOrgNames;
public void PopulateAssignedAppOrgData(FliveRetryContext context, App app)
{
var allOrgs = context.Org;
var appOrgs = new HashSet<int>(
app.OrgAppJoins.Select(c => c.OrgID));
AssignedAppOrgDataList = new List<AssignedAppOrgData>();
selectedOrgs = new List<SelectedAppOrgs>();
selectedOrgNames = new List<SelectedAppOrgNames>();
foreach (var org in allOrgs)
{
AssignedAppOrgDataList.Add(new AssignedAppOrgData
{
OrgID = org.ID,
Org = org.OrgName,
Assigned = appOrgs.Contains(org.ID)
});
if (appOrgs.Contains(org.ID))
{
selectedOrgs.Add(new SelectedAppOrgs
{
OrgID = org.ID
});
selectedOrgNames.Add(new SelectedAppOrgNames
{
OrgName = org.OrgName
});
}
}
}
public void UpdateAppOrgs(FliveRetryContext context,
string[] selectedOrgs, App appToUpdate)
{
if (selectedOrgs == null)
{
appToUpdate.OrgAppJoins = new List<OrgAppJoin>();
return;
}
var selectedOrgsHS = new HashSet<string>(selectedOrgs);
var appOrgs = new HashSet<int>
(appToUpdate.OrgAppJoins.Select(c => c.Org.ID));
foreach (var org in context.Org)
{
if (selectedOrgsHS.Contains(org.OrgName.ToString()))
{
if (!appOrgs.Contains(org.ID))
{
appToUpdate.OrgAppJoins.Add(
new OrgAppJoin
{
AppID = appToUpdate.ID,
OrgID = org.ID
});
}
}
else
{
if (appOrgs.Contains(org.ID))
{
OrgAppJoin orgToRemove
= appToUpdate
.OrgAppJoins
.SingleOrDefault(i => i.OrgID == org.ID);
context.Remove(orgToRemove);
}
}
}
}
Затем я обрабатываю их в OnGetAsync в Edit.cshtml.cs:
public async Task<IActionResult> OnGetAsync(int? id)
{
this.TreeData = GetOrgTreeData();
if (id == null)
{
return NotFound();
}
App = await _context.App
.Include(i => i.OrgAppJoins).ThenInclude(i => i.Org)
.Include(i => i.RoleAppJoins).ThenInclude(i => i.Role)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);
if (App == null)
{
return NotFound();
}
PopulateAssignedAppRoleData(_context, App);
PopulateAssignedAppOrgData(_context, App);
return Page();
}
и OnPostAsync
public async Task<IActionResult> OnPostAsync(int? id, string[] selectedOrgs, string[] selectedRoles)
{
if (!ModelState.IsValid)
{
return Page();
}
var appToUpdate = await _context.App
.Include(i => i.OrgAppJoins).ThenInclude(i => i.Org)
.Include(i => i.RoleAppJoins).ThenInclude(i => i.Role)
.FirstOrDefaultAsync(s => s.ID == id);
if (await TryUpdateModelAsync<App>(
appToUpdate,
"app", // Prefix for form value.
c => c.AppName, c => c.AppDescription, c => c.DisplayOrder))
{
UpdateAppOrgs(_context, selectedOrgs, appToUpdate);
UpdateAppRoles(_context, selectedRoles, appToUpdate);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
UpdateAppOrgs(_context, selectedOrgs, appToUpdate);
UpdateAppRoles(_context, selectedRoles, appToUpdate);
PopulateAssignedAppOrgData(_context, App);
PopulateAssignedAppRoleData(_context, App);
return Page();
}
. Это прекрасно работает при использовании множественных выпадающих списков иправильно читает и записывает во многие таблицы соединений.В данный момент я использую элементы управления кендо, но я рад использовать универсальные, если смогу найти решение своей проблемы.Мне нужно иметь древовидное представление для модели Org для отображения в виде множественного выбора, поэтому у меня есть два примера, которые я пытаюсь получить, которые ведут себя по-разному, DropDownTreeview не является необходимым, но на некоторых страницах это будет удобно, TreeView этосущественный.Первый - TreeView:
@(Html.Kendo().TreeView()
.Name("selectedOrgNames")
.DataTextField("OrgName")
.Checkboxes(checkboxes => checkboxes
.Name("ischecked")
.CheckChildren(true))
.HtmlAttributes(new { style = "width:100%" })
.DataSource(d => d
.Read(read =>
read.Url("/Apps/Edit?handler=Read")
)
)
)
Второй - DropDownTreeview:
@(Html.Kendo().DropDownTree()
.Placeholder("Select ...")
.Name("selectedOrgs")
.DataTextField("OrgName")
.DataValueField("ID")
.Checkboxes(checkboxes => checkboxes
.Name("ischecked")
.CheckChildren(true))
.AutoClose(false)
.Value(Model.selectedOrgNames)
.HtmlAttributes(new { style = "width:100%" })
.DataSource(d => d
.Read(read =>
read.Url("/Apps/Edit?handler=Read")
)
)
)
Оба примера читают источник данных отсюда в edit.cshtml.cs:
public IActionResult OnGetRead(int? id)
{
var result = from e in _context.Org
where id.HasValue ? e.ParentID == id : e.ParentID == null
select new
{
id = e.ID,
hasChildren = (from q in _context.Org
where (q.ParentID == e.ID)
select q
).Count() > 0,
OrgName = e.OrgName,
selected = (from s in _context.OrgAppJoin
where (s.OrgID == e.ID) && (s.AppID == 2)// <--this works, this doesn't--> (s.AppID == app.ID)
select s
).Count() > 0,
ischecked = (from s in _context.OrgAppJoin
where (s.OrgID == e.ID) && (s.AppID == 2)// <--this doesn't work, this doesn't either-->
(s.AppID == app.ID)
select s
).Count() > 0
};
return new JsonResult(result);
}
Моя первая проблема, вероятно, очень проста, я новичок в этой платформе: мне кажется, я не могу найти способ получить значение AppID со страницы в модуль OnGetRead (у меня жестко задан s.AppID== 2 в качестве тестового примера, чтобы увидеть, работает ли он) Я перепробовал все виды переменных и других методов.Идентификатор, передаваемый в OnPostAsync, а OnGetAsync - это идентификатор приложения, но идентификатор, передаваемый в OnGetRead, - это идентификатор организации, который является правильным и работает, но как использовать AppID со страницы для замены числа два вэта линия?где (s.OrgID == e.ID) && (s.AppID == 2)?
Моя вторая проблема - получение флажков для чтения и записи.DropDownTree выше записывает в базу данных правильно, но не читает и не заполняет флажки.Древовидное представление не заполняет флажки и не записывает данные в базу данных, однако оно СЧИТАЕТ выбранное значение из таблицы объединения для приложения № 2 (или любого другого числа, которое я вставляю вручную) в OnGetRead, и отображает различные цвета шрифтов и т. Д. Для правильных элементов.как выбрано, но не так, как проверено (aschecked может даже не быть действительным вызовом, но я не могу найти ссылку для этого).
Я чувствую, что я близко, но я пытался так долгозаставить это работать безрезультатно, в том числе и с телериком, который пытался помочь, но они не очень помогают в моделировании вашего собственного кода, только со статическими данными, и они, кажется, легки для приложения RazorБаза знаний и продолжайте давать примеры контроллеров с жестко закодированными данными.
Пожалуйста, сообщите, если мне нужно разделить это на два или более вопросов, но любая помощь будет высоко ценится
Спасибо