我有一个包含多个DropDowns的菜单。我添加了代码,但目前,它完全驻留在代码隐藏文件中。我想使用任何设计模式以简单而整洁的方式处理各种选择。
报告生成标准如下:
报告类型DropDown选项包括:
- 方案类型
- 方案逐
- 区逐
- 逐块
- 所有
醇>
默认情况下,仅启用第一个DropDown。从此DropDown中选择一个选项,可启用相应的DropDowns。
不仅如此,Scheme
,District
和Block
DropDowns的值也会在使用从任何这些DropDowns或Scheme Type
DropDown中选择项目时更改AJAX
它经常涉及各种SQL查询和启用/禁用DropDowns。我现在的代码变得混乱了许多IF
和EndIfs
。
我想知道是否使用Observer pattern
或使用Classes
的任何方法来简化此操作。有哪些方法可以使这些多项选择和DropDowns的填充变得易于管理和简单?
在下面编辑以明确要求
让我进一步澄清。
第一个DropDown是DropDown键,在页面打开时默认启用。默认情况下禁用所有其他DropDowns。但这并不意味着Cascading DropDown是正确的选择,因为从孩子DropDowns中选择是随机的。
整个计划是为每个DropDown以可理解的形式简化代码。根据选择,有许多Ifs和ElseIfs用于选择正确的查询。
例如:用户从报告类型主DropDown中选择District-wise report
。在这种情况下,启用了三个子DropDowns,即
Scheme Type
Scheme
District
如果用户从Scheme Types List中选择“ALL”,则所有类别中的所有类型的方案都会在Scheme DropDown中填充。
如果用户从选项中选择特定的方案类型:Urban,Rural或Other,则Scheme DropDown会过滤方案的名称。
现在,Scheme DropDown还有一个选项ALL。用户可以选择ALL或选择任何特定方案。
与区相同。如果选择了ALL,则Scheme DropDown中的方案将采用所有区域中的所有方案,但如果选择了特定区域,则Scheme DropDown必须填写此区域的过滤方案。
请注意,在这种情况下,我们现在正在以相反的顺序移动,因为District DropDown再次过滤Scheme DropDown。
同样适用于Block DropDown。
要检查其他所选选项,有多种条件。假设用户没有选择任何选项或用户选择ALL。
我想用每个DropDown的名称创建单独的类。对于DropDown中的任何更改,这些类应该保持听力通知(Observer)。
我想我能澄清一下。
答案 0 :(得分:5)
使用AJAX Control Toolkit是符合您要求的解决方案。
在AJAX Control Toolkit中,有CascadingDropDown Control
标记语法:
<ajaxToolkit:CascadingDropDown ID="ddlReportType" runat="server"
TargetControlID="ddlSchemeType"
Category="SchemeType"
PromptText="Please select a ReportType"
LoadingText="[Loading Report Types...]"
ServicePath="ReportService.asmx"
ServiceMethod="GetDropDownReportTypeContents"
ParentControlID="DropDownList1"
SelectedValue="SomeValue" />
然后你需要创建一个Web服务和几个Web方法,因为它具有以下方法签名,
[System.Web.Services.WebMethod]
[System.Web.Script.Services.ScriptMethod]
public CascadingDropDownNameValue[] GetDropDownReportTypeContents(
string knownTypeValues, string typevalue) { ... }
你使用if-Else-If做了类似的事情。如果答案是关于假设的,并且纯粹是实现的一个例子。
string query = "SELECT * FROM Reports";
List<string> filters = new List<string>();
bool ReportType = true;
bool SchemeType = true;
bool Scheme = true;
bool District = true;
bool Block = true;
if (ReportType)
filters.Add("ReportType = true");
if (SchemeType)
filters.Add("SchemeType = true");
if (Scheme)
filters.Add("Scheme = true");
if (District)
filters.Add("District = true");
if (Block)
filters.Add("Block = true");
if (filters.Count() > 0)
{
query = query + " WHERE " + string.Join(" AND ", filters.ToArray());
}
我希望我的回答可以帮助你
谢谢和问候
Harsh Baid
答案 1 :(得分:2)
因为看起来你可以使用Javascript完成所有这个客户端,为什么你这么多查询你的数据库?您应该持久保存数据客户端和服务器端。您可以调用所有相关的下拉数据,对其进行缓存,并从客户端调用WebMethod,该WebMethod将返回包含所需数据的JSON。对于服务器端对象持久性,您应该查看Entity Framework 4.1,其中每个对象都是表的表示。
我会将jQuery与Knockout JS一起使用,或者只使用jQuery,使用JSON在客户端持久保存数据,无需返回并转发到SQL服务器。
这是Knockout JS的一个很好的例子 http://knockoutjs.com/examples/cartEditor.html
当然,除非数据频繁变化。
答案 2 :(得分:2)
不完全是您正在寻找的内容,但您可能想了解我是如何使用jQuery在mvc中解决类似问题的。使用web methods代替mvc操作可以在webforms中实现相同。
这是一个分为3个部分的故事,代码可以在bitbucket上找到。您可以从表单第2部分开始,首先是创建演示应用程序和设置数据库。
http://blog.goranobradovic.com/2011/06/asp-net-mvc3-app-part-2-ajax-cascading-dropdown/
有2个下拉列表的工作示例,但我使用相同的解决方案3和4没有问题。
<强>更新强> 由于您有可用的来源,我将仅在此处更改相关行。防止多个ajax调用的调整将把选项的值放在第一个选择id(或id到值无关紧要),或者你可以在依赖的下拉列表中使用某些属性,如果你不能改变id和值,但我会保留这很简单。然后,在主下拉列表的更改事件中,检查是否需要加载目标:
$('#' + target.attr('cascading-dependson')).change(function () {
if($(this).find("option:selected").val() == $(target).attr("id")){ // this is added if
$(target).removeAttr("disabled"); // added
selectFromAjax($(target).attr('cascading-loadfrom'),
{ id: $(this).find("option:selected").val() },
target);
}
else { //added
$(target).attr("disabled", "disabled");
}
});
如果您不想使用id,则可以轻松更改此选项以使用select的某些自定义属性。
更新2
我刚刚看到你更新了问题。在我看来,有一种情况需要刷新所有依赖的下拉列表。为此你需要有所有下拉列表的id-s,需要在最后一个主选择选项的值中刷新,separeted即“,”,这样你就可以检查它的任何val().split(",")
是否等于依赖的id下拉列表,或者您可以在dependend中包含属性,该属性包含需要刷新的所有选项的值。您在我的代码中看到selectFromAjax的选项是下拉列表中的选定值和主字段的名称。由于您可能需要在此处使用服务器代码来处理您的某些值,我建议您使用第二种方法,即 - 将自定义属性添加到dependend下拉列表,其中您将从master中选择相关选项的值对于该字段,依赖项应在选中时加载。
你明白我的建议吗?
答案 3 :(得分:1)
如果我正确理解你的范例,那么,你有一个下拉列表(报告类型)决定是按方案类型,方案,区域或区块(或以上所有方式)进行选择。如果你不有“全部”选项,我建议要么只有两个下拉菜单(一个用于报告类型,另一个用于其标签更改以匹配)或者取消报告类型下拉菜单在每个其他人旁边放一个单选按钮,以选择你想要的。包含“全部”选项时,您可能不会使事情复杂化;例如,您可以再添加一个单选按钮并启用所有四个下拉列表。
但是,您询问观察者模式。从GoF开始,观察者模式在以下情况下非常有用:
我不完全确定这些情况适用于此。第二种情况与您的问题有一些相似之处,但您做知道需要改变什么以及如何改变。如果您正在进行的唯一更新是报告类型,则只需启用或禁用右侧下拉菜单即可。但是,您说其他下拉列表会相互影响,可能在“全部”选项中。即使在这种情况下,我也不确定Observer模式本身是最有帮助的。由于您使用SQL填充下拉列表,我猜您可能正在使用许多不同的存储过程(或即席查询),具体取决于您需要的参数。我建议的是每个下拉列表只有一个查询,明智地使用NULL
。例如,要从其他值填充Block,您可能有:
CREATE PROCEDURE GetBlocks
(
@SchemeTypeId INT NULL,
@SchemeId INT NULL,
@DistrictId INT NULL
)
AS
SELECT b.BlockId, b.BlockName
FROM Blocks b
INNER JOIN SchemeTypeBlocks stb ON b.BlockId = stb.BlockId
INNER JOIN SchemeBlocks sb ON b.BlockId = sb.BlockId
INNER JOIN DistrictBlocks db ON b.BlockId = db.BlockId
WHERE (@SchemeTypeId IS NULL OR stb.SchemeTypeId = @SchemeTypeId)
AND (@SchemeId IS NULL OR sb.SchemeId = @SchemeId)
AND (@DistrictId IS NULL OR db.DistrictId = @DistrictId)
ORDER BY b.BlockName
在不知道您的数据库的情况下,我不知道究竟会起什么作用,但我们的想法是,您只需将NULL
传递给尚未选择的任何内容。这可能会稍微简化您的代码。
如果这不能解答您的问题,请告诉我我可以澄清的内容。
答案 4 :(得分:1)
有一种简单的方法可以实现这一目标,请遵循以下方法: 首先,只需添加一个AjaxUpdatePanel ...然后在下拉菜单中将AutoPostBack属性设置为true, 进一步只需在OnSelectedIndexChanged事件上添加处理程序以启用第二次下拉..
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate><asp:DropDownList id="firstDrpDown" AutoPostBack="true"
OnSelectedIndexChanged="firstDropDown_SelectedIndexChanged"AppendDataBoundItems="true"
name="firstDropDown" runat="server">
<asp:DropDownList id="scndDrpDown" **AutoPostBack="true"**
OnSelectedIndexChanged="scndDropDown_SelectedIndexChanged" AppendDataBoundItems="true"
name="scndDropDown" runat="server" >
</ContentTemplate>
<asp:UpdatePanel>