现在出现了父类和子类一般都会存在一张表中,然后设计数据库的时候把父类的ID存到子类另一个字段中就实现了关联。
例如: 网站的左边导航 第一层就可以看做父类,里面就可以看做子类。
我们就先来看看怎么做导航。
效果图:
一切为了用户,这个只显示一个下面出来,不要显示多个不然很难看
① 前台页面
②样式 简单设置一下
③取数据 由于我们搭建的div的原因,想要显示出所有的数据需要用到Repter里面的数据绑定事件
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { Binging(); } } private void Binging() { DataSet ds = new FunctionDemo.BLL.Category().GetList("Pid=0"); replist.DataSource = ds.Tables[0]; replist.DataBind(); } ////// 每绑定一行就触发一次 一般这个方法用来加载每一行的子类数据 /// /// /// protected void replist_ItemDataBound(object sender, RepeaterItemEventArgs e) { Literal LitFirst = (Literal)e.Item.FindControl("LitFirst"); HiddenField hfId = (HiddenField)e.Item.FindControl("hfId"); ListcateModel = new FunctionDemo.BLL.Category().GetModelList("Pid=" + hfId.Value); foreach (FunctionDemo.Model.Category item in cateModel) { LitFirst.Text = LitFirst.Text + " "+item.Name+" "; } }
④数据的设计
父类 Pid=0 子类的Pid就是父类的ID LevalNum用来表示
第一种父子类就说到这,下面说的是第二种方式
其中的有个方法值得学习下
我们换成下拉框来试试 按分类显示数据 列: 父类 子类 父类 子类 。。
①页面
②代码
public FunctionDemo.BLL.Category categoryBLL = new FunctionDemo.BLL.Category(); protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { BingDDL(); } } public void BingDDL() { DataTable dt = categoryBLL.GetList("").Tables[0]; //categoryBLL.GetListChild(0, true); ddlDemo.Items.Add(new ListItem("类别", "0")); foreach (DataRow item in dt.Rows) { string title = ""; if (int.Parse(item["LevalNum"].ToString()) > 0) { title =" " + "|--" + item["Name"].ToString(); } else { title = item["Name"].ToString(); } ddlDemo.Items.Add(new ListItem(title, item["ID"].ToString())); } }
③显示效果
这一切尽是如此的完美,好像很好一样的。
我们做项目时并不是说所以的东西都是好的,很可能做了一半让你加几条数据,我们来试一试 NBA 加一条 ,爱好加一条,别找我加一条
我们的数据
然后再显示
我们如何把NBA子类往上面移动呢,这是问题的关键,那么就是查询数据的问题了。
我们改动了取数据的方法
然后显示数据
这样很符合我们的要求。
我们来看看这个方法写了什么。
////// 获取全部类别 /// /// 后面的bool值可以显示是否显示禁用的数据,这里并没做处理 ///public DataTable GetListChild(int PID, bool isState) { StringBuilder strSql = new StringBuilder(); strSql.Append("select ID,Name,Pid,LevalNum"); strSql.Append(" FROM Category "); //strSql.Append(" Where ParentId=" + PId); if (isState) { strSql.Append("Where 1=1 "); } strSql.Append(" order by Id asc"); DataSet ds = DbHelperSQL.Query(strSql.ToString()); 我们的数据查找完了,跟以前是一样的 DataTable oldData = ds.Tables[0] as DataTable; if (oldData == null) { return null; } //复制结构 DataTable newData = oldData.Clone(); clone()是基类Object的方法 //调用迭代组合成DAGATABLE 用旧数据得到新数据 GetChannelChild(oldData, newData, PID); return newData; } /// /// 获取子类别 /// /// 父编号 /// 状态 ///private void GetChannelChild(DataTable oldData, DataTable newData, int PId) { //第一遍进来的时候是获取父类 pid=0 我们只需每取一条父类数据,然后把改类的子类数据先加载进去就可以了 DataRow[] dr = oldData.Select("Pid=" + PId); for (int i = 0; i < dr.Length; i++) { //添加一行数据 DataRow row = newData.NewRow(); row["ID"] = int.Parse(dr[i]["ID"].ToString()); row["Name"] = dr[i]["Name"].ToString(); row["Pid"] = dr[i]["Pid"].ToString(); row["LevalNum"] = dr[i]["LevalNum"].ToString(); newData.Rows.Add(row); //调用自身迭代 this.GetChannelChild(oldData, newData, int.Parse(dr[i]["ID"].ToString())); //把父类的ID作为条件传进去,子类的数据就会出来 } }
这个方法是一种思想,会的话可以做别的事。
上面是满足我们的原数据和新数据都是在一张表,我们就可以用clone()方法,如果我的新表需要添加字段
//创建一个新的DataTable,这里可以添加我们的列 DataTable newData = new DataTable(); newData.Columns.Add("id", typeof(int)); newData.Columns.Add("parent_id", typeof(int)); newData.Columns.Add("class_layer", typeof(int)); newData.Columns.Add("nav_type", typeof(string)); newData.Columns.Add("name", typeof(string)); newData.Columns.Add("title", typeof(string)); newData.Columns.Add("sub_title", typeof(string)); newData.Columns.Add("icon_url", typeof(string)); newData.Columns.Add("link_url", typeof(string)); newData.Columns.Add("sort_id", typeof(int)); newData.Columns.Add("is_lock", typeof(int)); newData.Columns.Add("remark", typeof(string)); newData.Columns.Add("action_type", typeof(string)); newData.Columns.Add("is_sys", typeof(int));
//调用迭代组合成DAGATABLE 用旧数据得到新数据 GetChannelChild(oldData, newData, PID); return newData;
//在GetChannelChild()这个方法里面的添加数据里面就可以把新列的数据添加进去