3

我被一个问题困住了,我真的没想到会被耽搁这么多小时,这让我发疯

如标题中所述,我需要两个 DropDownLists,其中 ToYears 列表的值从 FromYear 的选择开始:

FromYear
2000
2001
2002
2003
2004

2002

2003
年 2004 年

所以我尝试使用 2 < asp:dropdownlist > 并在 FromYear 的 SelectedIndexEvent 期间更改选定的 ToYear ,但这会触发选定的 FromYear 事件,并且它不会再次触发。

现在我从 Ajax Control Toolkit 中找到了CascadingDropDown,并认为这可能是件好事。但我不想调用网络服务,而是想在实际页面后面的代码中使用方法。

回发后还应记住选择 - 年份范围根据后面代码中的属性而变化。

我在某处读到自动回发不适用于 CascadingDropDown。

您认为最优雅、最简单的解决方案是什么?

非常感谢您提前。

编辑:我将发布我的帖子的一些部分 - 希望对标记有所帮助:

    <asp:DropDownList AutoPostBack="True" ID="DropDownFromYear" runat="server"     OnSelectedIndexChanged="FromYearChanged" />
    <asp:Label ID="UntilLabel" runat="server" Text=" until " />
    <asp:UpdatePanel ID="ToYearUpdatePanel" runat="server" style="display: inline-block;">
        <ContentTemplate>
            <asp:DropDownList AutoPostBack="true" ID="DropDownToYear" runat="server" OnSelectedIndexChanged="ToYearChanged" />
        </ContentTemplate>
        <Triggers>
            <asp:AsyncPostBackTrigger ControlID="DropDownFromYear" EventName="SelectedIndexChanged" />
        </Triggers>
    </asp:UpdatePanel>

CodeBehind(从 OnInit 调用):

    private void InitializeDropDownYears()
    {

        //Calculate the YearMin YearMax Properties
        CalculateYearMinMax();

        int adaptedFromYear = 0, adaptedToYear = 0;

        //get the previously selected Years
        if (DropDownToYear.SelectedItem != null) adaptedToYear = int.Parse(DropDownToYear.SelectedValue);
        if (DropDownFromYear.SelectedItem != null) adaptedFromYear = int.Parse(DropDownFromYear.SelectedValue);

        //check the minimum year constraints 2005 was selected but minYear is 2010 -> adpated is set to 2010
        if (YearMin > adaptedFromYear || adaptedFromYear == 0) adaptedFromYear = YearMin;
        if (YearMax < adaptedToYear || adaptedToYear == 0) adaptedToYear = YearMax;

        //check the 5 year range constraint
        if ((YearMax - YearMin) > 5)
        {
            adaptedFromYear = DateTime.Now.Year - 2;
            adaptedToYear = DateTime.Now.Year + 2;
        }

        Dictionary<string, string> toYears = new Dictionary<string, string>();
        Dictionary<string, string> fromYears = new Dictionary<string, string>();

        for (int tempYear = YearMin; tempYear <= YearMax; tempYear++)
        {
            fromYears.Add(tempYear.ToString(), tempYear.ToString());
            if (tempYear >= adaptedFromYear)
            {
                toYears.Add(tempYear.ToString(), tempYear.ToString());
            }
        }

        DropDownFromYear.DataSource = fromYears;
        DropDownFromYear.DataValueField = "Key";
        DropDownFromYear.DataTextField = "Value";
        DropDownFromYear.SelectedValue = adaptedFromYear.ToString();
        DropDownFromYear.DataBind();

        DropDownToYear.DataSource = toYears;
        DropDownToYear.DataValueField = "Key";
        DropDownToYear.DataTextField = "Value";
        DropDownToYear.SelectedValue = adaptedToYear.ToString();
        DropDownToYear.DataBind();
        if(!IsPostBack)
        {
            SelectedFromYear = adaptedFromYear;
            SelectedToYear = adaptedToYear;
        }
    }

    private void CalculateYearMinMax()
    {
        IList<Task> taskList = CurrentLicense.TaskList;

        List<DateTime> startDates = taskList.Select(task => task.StartDate).ToList();
        YearMin = startDates.Min(date => date).Year;

        List<DateTime> endDates = taskList.Select(task => task.EndDate).ToList();
        YearMax = endDates.Max(date => date).Year;
    }

事件处理程序:

    protected void FromYearChanged(object sender, EventArgs e)
    {
        SelectedFromYear = int.Parse(DropDownToYear.SelectedValue);
        SelectedToYear = int.Parse(DropDownFromYear.SelectedValue);
        if (SelectedFromYear > SelectedToYear)
        {
            SelectedToYear = SelectedFromYear;
        }
        UpdateGanttTables();
    }

    protected void ToYearChanged(object sender, EventArgs e)
    {
        SelectedFromYear = int.Parse(DropDownToYear.SelectedValue);
        SelectedToYear = int.Parse(DropDownFromYear.SelectedValue);
        UpdateGanttTables();
    }
4

3 回答 3

1

填充DropDownList控制听起来很容易对吧?它是,当您使用 ASP.NET WebForms 的默认行为时。但是,当您想要获得特定功能时,您可能会遇到几个问题,例如,在 WebForms 中,尝试DropDownLists使用 AJAX 填充(这真的很痛苦,我找到的唯一解决方案是禁用页面上的安全检查<%@ Page EnableEventValidation="false"

以供参考:

如何填写 asp:DropDown 客户端?

由于您使用的是 WebForms 可能最好的方法是使用总UpdatePanel

例子:

结果

在此处输入图像描述

ASPX 标记

    <asp:ScriptManager runat="server" ID="sm" />
    <asp:UpdateProgress runat="server" AssociatedUpdatePanelID="updatePanel" DisplayAfter="0" DynamicLayout="true">
        <ProgressTemplate>
            Working...
        </ProgressTemplate>
    </asp:UpdateProgress>
    <asp:UpdatePanel runat="server" ID="updatePanel">
        <ContentTemplate>
            <div>
                <asp:Label ID="Label1" Text="From" runat="server" AssociatedControlID="from" />
            </div>
            <div>
                <asp:DropDownList runat="server" ID="from" AutoPostBack="true" CausesValidation="false" OnSelectedIndexChanged="from_SelectedIndexChanged">
                </asp:DropDownList>
            </div>
            <div>
                <asp:Label ID="Label2" Text="To" runat="server" AssociatedControlID="to" />
            </div>
            <div>
                <asp:DropDownList runat="server" ID="to" />
            </div>
        </ContentTemplate>
    </asp:UpdatePanel>

后面的页面代码

    private const int MaxYear = 2030;
    private const int MinYear = 1959;

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!this.IsPostBack)
        {
            var fromRange = Enumerable.Range(MinYear, MaxYear - MinYear);

            this.from.DataSource = fromRange;
            this.from.DataBind();
        }
    }

    protected void from_SelectedIndexChanged(object sender, EventArgs e)
    {
        var selectedYear = Convert.ToInt32(this.from.SelectedValue);
        var toRange = Enumerable.Range(selectedYear, MaxYear - selectedYear);

        this.to.DataSource = toRange;
        this.to.DataBind();
    }

我刚刚将此示例上传到我的 GitHub 以供参考

于 2012-10-01T18:47:40.480 回答
0

最后,我想通了并得到了-我认为这是一个不错的解决方案,因为它使我能够:

  • 最初用数据填充两个 DDL
  • 在两个 DDL 中预选项目
  • 仍然在页面上使用 EnableEventValidation="true"
  • 我可以通过简单地调用 DataBind() 来更新 DDL;在他们

与我之前的方法的主要区别在于,我在 DDL 的 OnDataBinding 事件期间填充了数据。因此,当我在 PageLoad 期间执行 DataBind() 时,它会自动发生。我首先要确保的唯一一件事是填写包含我的信息的字典。

如果我想从 FromYearsDDL 的 selectionChangeEvent 更新 ToYearsDDL,我只需更新 ToYearsDDL 的数据并调用 ToYearsDDL.DataBind();

希望这可以帮助遇到同一堵墙的其他人!

标记来了:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="LinkedDropDownsBound.aspx.cs"
    Inherits="ASP.Net_Spielwiese.LinkedDropDownsBound"  EnableEventValidation="true" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <div>
        <asp:UpdatePanel runat="server" ID="updatePanel">
            <ContentTemplate>
                <div>
                    <asp:Label ID="FromLabel" Text="From" Enabled="false" runat="server"  />
                </div>
                <div>
                    <asp:DropDownList runat="server" ID="FromYearsDDL" AutoPostBack="true" CausesValidation="false" OnDataBinding="DDLFromDataBind"
                        OnSelectedIndexChanged="DDLFromSelectedIndexChanged">
                    </asp:DropDownList>
                </div>
                <div>
                    <asp:Label ID="ToLabel" Text="To" Enabled="false" runat="server" />
                </div>
                <div>
                    <asp:DropDownList runat="server" ID="ToYearsDDL" AutoPostBack="true" CausesValidation="false" OnDataBinding="DDLToDataBind"
                        OnSelectedIndexChanged="DDLToSelectedIndexChanged"/>
                </div>
            </ContentTemplate>
        </asp:UpdatePanel>
    </div>
    </form>
</body>
</html>

这是后面的代码:

public partial class LinkedDropDownsBound : System.Web.UI.Page
{
    public Dictionary<String, Boolean> FromYears
    {
        get
        {
            if (ViewState["FromYears"] == null)
            {
                ViewState["FromYears"] = new Dictionary<String, Boolean>();
            }
            return ViewState["FromYears"] as Dictionary<String, Boolean>;
        }
        set
        {
            ViewState["FromYears"] = value;
        }
    }
    public Dictionary<String, Boolean> ToYears
    {
        get
        {
            if (ViewState["ToYears"] == null)
            {
                ViewState["ToYears"] = new Dictionary<String, Boolean>();
            }
            return ViewState["ToYears"] as Dictionary<String, Boolean>;
        }
        set
        {
            ViewState["ToYears"] = value;
        }
    }

    public int MinYear = 1975;
    public int MaxYear = 2015;


    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            InitFromYears();
            InitToYears();
            DataBind();
        }
    }

    private void InitFromYears()
    {
        FromYears = new Dictionary<string, bool>();
        IEnumerable<int> fromRange = Enumerable.Range(MinYear, MaxYear - MinYear);

        foreach (var fromYear in fromRange)
        {
            FromYears.Add(fromYear.ToString(), fromYear == (DateTime.Now.Year - 2));
        }
    }

    private void InitToYears()
    {
        ToYears = new Dictionary<string, bool>();
        //get the selected FromYear Value
        int minToYear = Convert.ToInt32(FromYears.FirstOrDefault(dict => dict.Value).Key);
        //make sure ToYears is at least FromYears
        if (minToYear < Convert.ToInt32(FromYears.Min(k => k.Key)))
        {
            minToYear = Convert.ToInt32(FromYears.Min(k => k.Key));
        }
        IEnumerable<int> toRange = Enumerable.Range(minToYear, MaxYear - minToYear);
        foreach (var toYear in toRange)
        {
            ToYears.Add(toYear.ToString(), toYear == (DateTime.Now.Year + 2));
        }
    }

    protected void DDLFromDataBind(object sender, EventArgs e)
    {
        FromYearsDDL.DataSource = FromYears;
        FromYearsDDL.DataValueField = "Key";
        FromYearsDDL.DataTextField = "Key";
        FromYearsDDL.SelectedValue = FromYears.FirstOrDefault(y => y.Value).Key;
    }

    protected void DDLFromSelectedIndexChanged(object sender, EventArgs e)
    {
        //update the FromYear Dictionary
        var tempDictionary = FromYears.ToDictionary(fromYear => fromYear.Key, fromYear => fromYear.Key.Equals(FromYearsDDL.SelectedValue));
        FromYears = tempDictionary;

        //Call Bind on the ToYear DDL
        ToYearsDDL.DataBind();

        //do my other update stuff here
        FromLabel.Text = FromYearsDDL.SelectedValue;
        ToLabel.Text = ToYearsDDL.SelectedValue;
    }

    protected void DDLToSelectedIndexChanged(object sender, EventArgs e)
    {
        //do my other update stuff here
        FromLabel.Text = FromYearsDDL.SelectedValue;
        ToLabel.Text = ToYearsDDL.SelectedValue;
    }

    protected void DDLToDataBind(object sender, EventArgs e)
    {
        InitToYears();
        ToYearsDDL.DataSource = ToYears;
        ToYearsDDL.DataValueField = "Key";
        ToYearsDDL.DataTextField = "Key";
        ToYearsDDL.SelectedValue = ToYears.FirstOrDefault(y => y.Value).Key;
    }
}
于 2012-10-02T15:28:17.883 回答
0

这是 HTML 页面

在c#页面后面的代码中

private void BindYearDropdown()
        {
            int year;

            for (year = DateTime.Now.Year; year >= 2010 ; year--)
            {
                DDLYear.Items.Add(year.ToString());
            }
        }

上面的代码适用于 Years Back 病房

于 2016-02-24T15:00:56.347 回答