2个年度范围的下拉列表

时间:2012-10-01 17:41:00

标签: c# asp.net webforms viewstate

我遇到了一个问题,我真的没想到会被耽误这么多时间,这让我感到疯狂

正如标题中所提到的,我需要两个DropDownLists,其中ToYears List的值从FromYear的选择开始:

FromYear
2000
2001年
2002
2003
2004年

ToYear
2002
2003
2004年

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

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

此外,应该在回发后记住选择 - 并且年份的范围根据后面的代码中的属性而变化。

我在某地读过autopostback不能与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();
    }

3 个答案:

答案 0 :(得分:1)

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

供参考:

How to fill an asp:DropDown client side?

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

示例:

结果

enter image description here

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();
    }

I just uploaded this sample to my GitHub for reference

答案 1 :(得分:0)

最后我想出来并得到了 - 因为我认为这是一个很好的解决方案,因为它使我能够:

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

与我以前的方法的主要区别在于,我在OnDataBinding事件期间用DDL填充数据。所以当我在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;
    }
}

答案 2 :(得分:0)

这是HTML页面
 

在c#page背后的代码中

private void BindYearDropdown()
        {
            int year;

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

以上代码适用于岁月病房