好吧,下面我粘貼了工作示例。 事情需要注意的:
Message=Failed to load viewstate. The control tree into which viewstate is being loaded must match the control tree that was used to save viewstate during the previous request. For example, when adding controls dynamically, the controls added during a post-back must match the type and position of the controls added during the initial request. Source=System.Web ErrorCode=-2147467259
設定這個屬性上的動態控件
EnableViewState = false
數據在這個例子中是這樣
品牌引擎顏色成本
VW,1.2,黑色,72 000
VW,1.2,白色,70 000
VW,1.6 TDI,紅,79 500
VW,1.6 TDI,白色,78 800
福特1.6,黑色,57 600
福特,1.6,綠化,57 100
福特,2.0 TDCI,黑色,87 300
福特,2.0 TDCI,白色,86 600
Basicaly這就像這個:
- 選擇汽車品牌和選擇按鈕(按鈕是我們的世代控制標準) 當然,你也可以做下降等邏輯。
- 在第二屏幕上,您有一個或兩個下拉式選單,根據您選擇的
- 如果你有兩個下拉菜單,二是取決於第一個下拉的選擇,讓你有依賴的例子,回傳
頁面代碼:
<form id="form1" runat="server">
<div>
<asp:MultiView ID="mvPanels" runat="server">
<asp:View ID="vPanel1" runat="server">
<table>
<tbody>
<tr>
<td>Pick car</td>
<td><asp:DropDownList ID="ddlBrand" runat="server" /></td>
<td><asp:Button ID="btnPanel1Next" Text="Next" runat="server"
onclick="btnPanel1Next_Click" /></td>
<td><asp:Button ID="btnPanel1NextEngineOnly" Text="Next (pick engine only)" runat="server"
onclick="btnPanel1NextEngineOnly_Click" /></td>
</tr>
</tbody>
</table>
</asp:View>
<asp:View ID="vPanel2" runat="server">
<%--<table>
<tbody>
<tr>
<td>Pick engine</td>
<td><asp:DropDownList ID="ddlEngine" AutoPostBack="true" runat="server"
onselectedindexchanged="ddlEngine_SelectedIndexChanged" /></td>
<td><asp:DropDownList ID="ddlColor" AutoPostBack="true" runat="server"
onselectedindexchanged="ddlColor_SelectedIndexChanged" /></td>
<td><asp:Button ID="btnPanel2Prev" Text="Prev" runat="server"
onclick="btnPanel2Prev_Click" /><asp:Button ID="btnPanel2Next" Text="Next"
runat="server" Enabled="False" onclick="btnPanel2Next_Click" /></td>
</tr>
</tbody>
</table>--%>
</asp:View>
<asp:View ID="vPanel3" runat="server">
<table>
<tbody>
<tr>
<td><asp:Label ID="lblResult" runat="server" /></td>
<td><asp:Button ID="btnPanel3Prev" Text="Prev" runat="server"
onclick="btnPanel3Prev_Click" /><asp:Button ID="btnPanel3Finish"
Text="Confirm" runat="server" onclick="btnPanel3Finish_Click" /></td>
</tr>
</tbody>
</table>
</asp:View>
</asp:MultiView>
</div>
</form>
後面的代碼:
public partial class Default : System.Web.UI.Page
{
public class CarConfiguration
{
public string Brand { get; set; }
public string Engine { get; set; }
public PaintColor Paint { get; set; }
public string Cost { get; set; }
}
[Serializable]
public class CarConfigurationFilter
{
public string Brand { get; set; }
public string Engine { get; set; }
public PaintColor? Paint { get; set; }
public bool EngineOnly { get; set; }
}
public enum PaintColor
{
Black,
Red,
White,
Green,
}
public List<CarConfiguration> availableCars = new List<CarConfiguration>
{
new CarConfiguration{
Brand = "VW",
Engine = "1.2",
Paint = PaintColor.Black,
Cost = "72 000",
},
new CarConfiguration{
Brand = "VW",
Engine = "1.2",
Paint = PaintColor.White,
Cost = "70 000",
},
new CarConfiguration{
Brand = "VW",
Engine = "1.6 TDI",
Paint = PaintColor.Red,
Cost = "79 500"
},
new CarConfiguration{
Brand = "VW",
Engine = "1.6 TDI",
Paint = PaintColor.White,
Cost = "78 800",
},
new CarConfiguration{
Brand = "Ford",
Engine = "1.6",
Paint = PaintColor.Black,
Cost = "57 600"
},
new CarConfiguration{
Brand = "Ford",
Engine = "1.6",
Paint = PaintColor.Green,
Cost = "57 100"
},
new CarConfiguration{
Brand = "Ford",
Engine = "2.0 TDCi",
Paint = PaintColor.Black,
Cost = "87 300"
},
new CarConfiguration{
Brand = "Ford",
Engine = "2.0 TDCi",
Paint = PaintColor.White,
Cost = "86 600"
},
};
CarConfigurationFilter filter
{
get { return (CarConfigurationFilter)ViewState["Filter"]; }
set { ViewState["Filter"] = value; }
}
//If you have multiview in control you need to create this in event before event PageLoad like LoadViewState, LoadControlState, LoadControlState
protected override void OnPreLoad(EventArgs e)
{
if (IsPostBack && mvPanels.ActiveViewIndex == 1)
{
CreateControlsOnPanel2(true, !filter.EngineOnly);
}
base.OnPreLoad(e);
}
protected override void OnLoad(EventArgs e)
{
if (!IsPostBack)
{
ddlBrand.DataSource = availableCars.Select(x => x.Brand).Distinct();
ddlBrand.DataBind();
filter = new CarConfigurationFilter();
mvPanels.ActiveViewIndex = 0;
}
base.OnLoad(e);
}
protected void btnPanel1Next_Click(object sender, EventArgs e)
{
filter.Brand = ddlBrand.SelectedValue;
filter.EngineOnly = false;
CreateControlsOnPanel2(true, true);
mvPanels.ActiveViewIndex++;
}
protected void btnPanel1NextEngineOnly_Click(object sender, EventArgs e)
{
filter.Brand = ddlBrand.SelectedValue;
filter.EngineOnly = true;
CreateControlsOnPanel2(true, false);
mvPanels.ActiveViewIndex++;
}
void CreateControlsOnPanel2(bool enginePickerEnabled, bool colorPickerEnabled)
{
var btnPanel2Prev = new Button();
btnPanel2Prev.ID = "btnPanel1Prev";
btnPanel2Prev.EnableViewState = false;
btnPanel2Prev.Text = "Prev";
btnPanel2Prev.Click += btnPanel2Prev_Click;
var btnPanel2Next = new Button();
btnPanel2Next.ID="btnPanel2Next";
btnPanel2Next.Text = "Next";
btnPanel2Next.EnableViewState = false;
btnPanel2Next.Enabled = false;
btnPanel2Next.Click += btnPanel2Next_Click;
if (enginePickerEnabled)
{
var ddlEngine = new DropDownList();
ddlEngine.ID = "ddlEngine";
ddlEngine.AutoPostBack = true;
ddlEngine.EnableViewState = false;
var engines = availableCars.Where(x => x.Brand == filter.Brand).Select(found => found.Engine).Distinct().ToList();
engines.Insert(0, String.Empty);
ddlEngine.DataSource = engines;
ddlEngine.DataBind();
if (!String.IsNullOrEmpty(filter.Engine))
{
ddlEngine.SelectedValue = filter.Engine;
if (!colorPickerEnabled)
btnPanel2Next.Enabled = true;
}
else
ddlEngine.SelectedIndex = 0;
ddlEngine.SelectedIndexChanged += ddlEngine_SelectedIndexChanged;
vPanel2.Controls.Add(ddlEngine);
}
//remember to add ID to all dynamic controls or there might be an error on postback
if (colorPickerEnabled)
{
var ddlColor = new DropDownList();
ddlColor.ID = "ddlColor";
ddlColor.AutoPostBack = true;
ddlColor.EnableViewState = false;
ddlColor.SelectedIndexChanged += ddlColor_SelectedIndexChanged;
vPanel2.Controls.Add(ddlColor);
if (!String.IsNullOrEmpty(filter.Engine))
{
var colors = availableCars.Where(x => x.Brand == filter.Brand && x.Engine == filter.Engine).Select(found => found.Paint.ToString()).Distinct().ToList();
colors.Insert(0, String.Empty);
ddlColor.DataSource = colors;
if (filter.Paint.HasValue)
{
ddlColor.SelectedValue = filter.Paint.Value.ToString();
btnPanel2Next.Enabled = true;
}
}
else
{
ddlColor.DataSource = null;
ddlColor.SelectedIndex = 0;
}
ddlColor.DataBind();
}
vPanel2.Controls.Add(btnPanel2Prev);
vPanel2.Controls.Add(btnPanel2Next);
}
protected void ddlEngine_SelectedIndexChanged(object sender, EventArgs e)
{
var ddlEngine = sender as DropDownList;
var btnPanel2Next = (Button)vPanel2.FindControl("btnPanel2Next");
if (!String.IsNullOrEmpty(ddlEngine.SelectedValue))
{
filter.Engine = ddlEngine.SelectedValue;
var colors = availableCars.Where(x => x.Brand == filter.Brand && x.Engine == filter.Engine).Select(found => found.Paint.ToString()).Distinct().ToList();
colors.Insert(0, String.Empty);
filter.Paint = null;
var ddlColor = (DropDownList)vPanel2.FindControl("ddlColor");
if (ddlColor != null)
{
ddlColor.DataSource = colors;
ddlColor.DataBind();
ddlColor.SelectedIndex = 0;
btnPanel2Next.Enabled = false;
}
else
btnPanel2Next.Enabled = true;
}
else
{
var ddlColor = (DropDownList)vPanel2.FindControl("ddlColor");
if (ddlColor != null)
{
ddlColor.Items.Clear();
ddlColor.SelectedIndex = -1;
}
filter.Engine = null;
btnPanel2Next.Enabled = false;
}
}
protected void ddlColor_SelectedIndexChanged(object sender, EventArgs e)
{
var ddlColor = (DropDownList)vPanel2.FindControl("ddlColor");
var btnPanel2Next = (Button)vPanel2.FindControl("btnPanel2Next");
if (!String.IsNullOrEmpty(ddlColor.SelectedValue))
{
filter.Paint = (PaintColor)Enum.Parse(typeof(PaintColor), ddlColor.SelectedValue);
btnPanel2Next.Enabled = true;
}
else
{
filter.Paint = null;
btnPanel2Next.Enabled = false;
}
}
protected void btnPanel2Prev_Click(object sender, EventArgs e)
{
filter.Engine = null;
filter.Paint = null;
mvPanels.ActiveViewIndex--;
}
protected void btnPanel2Next_Click(object sender, EventArgs e)
{
mvPanels.ActiveViewIndex++;
var selectedConfiguration = availableCars.Where(x => x.Brand == filter.Brand && x.Engine == filter.Engine
&& (!filter.Paint.HasValue || x.Paint == filter.Paint)).Distinct().FirstOrDefault();
if (selectedConfiguration != null)
lblResult.Text = String.Format("You have selected {0} {1} {2} for {3} PLN", selectedConfiguration.Brand,
selectedConfiguration.Engine, selectedConfiguration.Paint, selectedConfiguration.Cost);
}
protected void btnPanel3Prev_Click(object sender, EventArgs e)
{
mvPanels.ActiveViewIndex--;
CreateControlsOnPanel2(true, !filter.EngineOnly);
}
protected void btnPanel3Finish_Click(object sender, EventArgs e)
{
}
}
如果您有任何額外的問題,我會很樂意幫助
你在做什麼與第二面板的數據,有沒有任何按鈕,回發等?如果您在OnInit之後創建控件,它們仍然被創建,但回發數據不會自動設置。因此,如果您在第二個面板上調用回發,並且需要來自這些動態控件的數據,則需要從Request.Forms [dynamicControlClientId]獲取OnInit中的數據,或者將其存儲在ViewState中。另一個問題是你需要在回發後看到動態控件,所以你必須在第二個面板上存儲信息,以便如何在回發時創建控件(從第一個面板開始)。 – pawciu
是的,會有更多的回傳。在所有的多視圖中有4個步驟,所以前3個會在回到下一步時回發。 – dotnetnoob