我自己写了2个方法,但实现起来都有问题.
要求:
1.点击子级,父节点不被选中。
2.点击父节点,子节点全部选中
3.点击文字时效果要与点击CheckBox一样.(说明,点击一次文字选中复选框,下面的所有自己的复选框都被选中。再点则取消选中!)
这是我自己写的
Demo1:(问题,只能通过选中复选框来实现效果,而且不支持火狐)
Page:
<asp:TreeView ID="TreeV2" runat="server" ShowLines="True" OnTreeNodeCheckChanged="TreeView1_TreeNodeCheckChanged"> </asp:TreeView> Page JS: // 点击复选框时触发事件 function postBackByObject() { var o = window.event.srcElement; if ((o.tagName == "INPUT" && o.type == "checkbox") || o.tagName == "A") { //这里的第一个参数是UpdatePanel ID,因为我使用了MS的ASPAJAX来实现局部刷新 //如果没有使用MS的ASPAJAX,这里的两个参数都可以为空 __doPostBack("", ""); } }
Code:
1 //号码簿 2 private void BindWEmail() 3 { 4 TreeV2.Nodes.Clear(); 5 string sql = "select * from SMS_NumberGroup where 1=1";//查询组 6 if (ht["Detail"] == null) 7 sql += " and (Levels=1 or (Levels=0 and UIDS like '%," + UserInfo.UserId + ",%'))"; 8 9 DataTable dt = Iwoak.ExecSQL.ExecuteDataTable(sql); 10 BindTree(dt, 0, null, TreeV2); 11 TreeV2.ShowCheckBoxes = TreeNodeTypes.All;// 12 TreeV2.Attributes.Add("onclick", "postBackByObject()"); 13 //TreeV2.Attributes.Add("onclick", "OnTreeNodeChecked(event);"); 14 } 15 /// <summary> 16 /// 绑定Tree 17 /// </summary> 18 /// <param name="dt">数据集</param> 19 /// <param name="parentId">链接ID</param> 20 /// <param name="pNode">操作节点</param> 21 /// <param name="tv"></param> 22 private void BindTree(DataTable dt, int parentId, TreeNode pNode, TreeView tv) 23 { 24 DataView dv = new DataView(dt); 25 dv.RowFilter = "[mid]=" + parentId; 26 foreach (DataRowView drv in dv) 27 { 28 TreeNode tNode = new TreeNode(); 29 tNode.ShowCheckBox = true; 30 31 string ID = drv["ID"].ToString(); 32 System.Text.StringBuilder sb = new System.Text.StringBuilder(); 33 sb.AppendFormat(" <span title='{0}'>" + drv["SName"].ToString() + "</span> ", drv["Remark"]); 34 tNode.Text = sb.ToString(); 35 tNode.Value = ID; 36 DataTable dtf = Iwoak.ExecSQL.ExecuteDataTable("select * from [SMS_Number] where nid=" + ID + GetQueryW()); 37 if (pNode == null) 38 { 39 #region 联系人 40 41 for (int i = 0; i < dtf.Rows.Count; i++) 42 { 43 DataRow dr = dtf.Rows[i]; 44 TreeNode p2 = new TreeNode(); 45 p2.ShowCheckBox = true; 46 p2.Text = string.Format("<a href=\"javascript:void();\" title='{2}'>{1} {0}</a>", dr["Phone"], dr["Contact"], dr["Remark"]); 47 p2.Value = dr["Phone"].ToString(); 48 tNode.ChildNodes.Add(p2); 49 } 50 #endregion 51 tv.Nodes.Add(tNode); 52 tNode.Expanded = true; 53 BindTree(dt, Convert.ToInt32(drv["ID"]), tNode, tv); 54 55 } 56 else 57 { 58 pNode.ChildNodes.Add(tNode); 59 tNode.Expanded = true; 60 BindTree(dt, Convert.ToInt32(drv["ID"]), tNode, tv); 61 #region 联系人 62 for (int i = 0; i < dtf.Rows.Count; i++) 63 { 64 DataRow dr = dtf.Rows[i]; 65 TreeNode p2 = new TreeNode(); 66 //p2.ShowCheckBox = true; 67 p2.Text = string.Format("<a href=\"javascript:void());\" title='{2}'>{1} {0}</a>", dr["Phone"], dr["Contact"], dr["Remark"]); 68 p2.Value = dr["Phone"].ToString(); 69 tNode.ChildNodes.Add(p2); 70 } 71 #endregion 72 } 73 74 } 75 }
Demo2:(问题,点击文字时,自身的复选框选中,但子级没有选中,支持火狐)
Page:
1 <asp:TreeView ID="tvDept" runat="server" AllowCascadeCheckbox="True" CssClass="treelink" 2 OnTreeNodeCheckChanged="TreeView1_TreeNodeCheckChanged" CollapseImageUrl="~/CommonFiles/imgs/SystemImg/file.gif" 3 ExpandImageUrl="~/CommonFiles/imgs/SystemImg/folder.gif"> 4 <SelectedNodeStyle CssClass="treelink" /> 5 <NodeStyle CssClass="treelink" /> 6 </asp:TreeView> 7 Page JS: 8 9 <script type="text/javascript"> 10 // $(function() { 11 // parent.ymPrompt.max(); 12 // }); 13 // 点击复选框时触发事件 14 function postBackByObject() { 15 var o = window.event.srcElement; 16 if ((o.tagName == "INPUT" && o.type == "checkbox") || o.tagName == "A") { 17 //这里的第一个参数是UpdatePanel ID,因为我使用了MS的ASPAJAX来实现局部刷新 18 //如果没有使用MS的ASPAJAX,这里的两个参数都可以为空 19 __doPostBack("", ""); 20 } 21 } 22 function OnTreeNodeChecked(e) //单击父节点子结点选中的代码 23 { 24 if (window.event) e = window.event; 25 var evt = e.srcElement ? e.srcElement : e.target; 26 if (evt.type != undefined || evt.tagName != undefined) { 27 28 if (evt.type == 'checkbox') { 29 var childrenDivID = evt.id.replace('CheckBox', 'Nodes'); 30 var div = document.getElementById(childrenDivID); 31 if (div == null) return; 32 var checkBoxs = div.getElementsByTagName('INPUT'); 33 for (var i = 0; i < checkBoxs.length; i++) { 34 if (checkBoxs[i].type == 'checkbox') 35 checkBoxs[i].checked = evt.checked; 36 } 37 38 } 39 else if (evt.tagName == "A") { 40 if (evt.previousSibling && evt.previousSibling.tagName == "INPUT" && evt.previousSibling.type == "checkbox") { 41 // evt.previousSibling.checked = true; 42 evt.previousSibling.checked = evt.previousSibling.checked ? false : true; 43 } 44 if (window.event) { 45 window.event.cancelBubble = true; 46 window.event.returnValue = false; 47 } 48 else { 49 e.stopPropagation(); 50 } 51 52 } 53 } 54 } 55 </script>
Code:
1 #region 页面加载时执行 2 protected void Page_Load(object sender, EventArgs e) 3 { 4 if (!IsPostBack) 5 { 6 Common_BindTree(rule.GetDept(), 0, (TreeNode)null, this.tvDept); 7 tvDept.ShowCheckBoxes = TreeNodeTypes.All;// 8 tvDept.Attributes.Add("onclick", "OnTreeNodeChecked(event);"); 9 } 10 } 11 #endregion 12 //初始化部门 13 public void Common_BindTree(DataSet ds, int parentId, TreeNode pNode, TreeView tv) 14 { 15 DataView dv = new DataView(ds.Tables[0]); 16 dv.RowFilter = "[CID]=" + parentId; 17 foreach (DataRowView drv in dv) 18 { 19 TreeNode tNode = new TreeNode(); 20 21 tNode.Text = drv["Name"].ToString(); 22 tNode.ShowCheckBox = true; 23 tNode.NavigateUrl = "#"; 24 tNode.Value = drv["ID"].ToString(); 25 26 if (ViewState["Selected"] != null) 27 { 28 DataTable dt = (DataTable)ViewState["Selected"]; 29 for (int i = 0; i < dt.Rows.Count; i++) 30 { 31 if (dt.Rows[i]["DeptID"].ToString() == tNode.Value) 32 { 33 tNode.Checked = true; 34 } 35 } 36 37 } 38 39 //添加该节点下的所有用户 40 Iw_UsersRule rule = new Iw_UsersRule(); 41 DataSet UsersDs = rule.GetUsers(tNode.Value); 42 if (UsersDs.Tables[0].Rows.Count > 0) 43 { 44 for (int k = 0; k < UsersDs.Tables[0].Rows.Count; k++) 45 { 46 string UserID = UsersDs.Tables[0].Rows[k]["ID"].ToString(); 47 string UserName = UsersDs.Tables[0].Rows[k]["UserName"].ToString(); 48 TreeNode NodeUser = new TreeNode(); 49 NodeUser.Text = UserName; 50 NodeUser.Value = "User_" + UsersDs.Tables[0].Rows[k]["ID"].ToString(); 51 NodeUser.ImageUrl = "~/CommonFiles/imgs/MenuImages/employee.gif"; 52 NodeUser.ShowCheckBox = true; 53 if (Request.QueryString["ChooseUserID"] != null && Request.QueryString["ChooseUserID"] != "")//再次选择时显示上次已选中的项 54 { 55 string[] ChooseDeptID = Request.QueryString["ChooseUserID"].Split(','); 56 for (int j = 0; j < ChooseDeptID.Length; j++) 57 { 58 if (UserID == ChooseDeptID[j].ToString()) 59 NodeUser.Checked = true; 60 } 61 } 62 63 tNode.ChildNodes.Add(NodeUser); 64 } 65 } 66 //父节点 67 if (pNode == null) 68 { 69 tv.Nodes.Add(tNode); 70 tNode.Expanded = true; 71 72 73 Common_BindTree(ds, Convert.ToInt32(drv["ID"]), tNode, tv); 74 } 75 else 76 { 77 78 pNode.ChildNodes.Add(tNode); 79 Common_BindTree(ds, Convert.ToInt32(drv["ID"]), tNode, tv); 80 } 81 } 82 }
昨晚刚有人问类似的问题,你看一下
这个不能满足我的需求
@小明冥: 你一定要现成的?自己实现会更有成就感,
这个代码应该能给你思路了,只要再稍微改一下
@田林九村: 当然啦,我是要应该在项目中的。
参考这个试试,貌似能实现前两个要求:
public class TreeItemModel : INotifyPropertyChanged { /// <summary> /// 結点の選択状態 /// </summary> bool? _isChecked = false; /// <summary> /// プロパティ変更イベント /// </summary> public event PropertyChangedEventHandler PropertyChanged; /// <summary> /// 結点の選択状態プロパティ /// </summary> public bool? IsChecked { get { return _isChecked; } set { this.SetIsChecked(value, true, true); } } /// <summary> /// 子結点集合 /// </summary> public ObservableCollection<TreeItemModel> Items { get; set; } /// <summary> /// 親結点プロパティ /// </summary> public TreeItemModel Parent { get; set; } /// <summary> /// 文字プロパティ /// </summary> public string Text { get; set; } /// <summary> /// コンストラクタ /// </summary> public TreeItemModel() { Items = new ObservableCollection<TreeItemModel>(); } /// <summary> /// プロパティ変更イベント /// </summary> /// <param name="prop"></param> void OnPropertyChanged(string prop) { if (this.PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs(prop)); } /// <summary> /// 結点の選択状態を更新する /// </summary> /// <param name="value">選択状態値</param> /// <param name="updateSub">子結点</param> /// <param name="updateParent">親結点</param> void SetIsChecked(bool? value, bool updateSub, bool updateParent) { if (value == _isChecked) return; _isChecked = value; if (updateSub && _isChecked.HasValue) { foreach (TreeItemModel child in Items) { child.SetIsChecked(_isChecked, true, false); } } if (updateParent && Parent != null) { Parent.VerifyCheckState(); } this.OnPropertyChanged("IsChecked"); } /// <summary> /// 検査選択状態 /// </summary> void VerifyCheckState() { bool? state = null; for (int i = 0; i < this.Items.Count; ++i) { bool? current = this.Items[i].IsChecked; if (i == 0) { state = current; } else if (state != current) { state = null; break; } } this.SetIsChecked(state, false, true); } }
<script type="text/javascript">
function ClickTree() {
var o = window.event.srcElement;
if (o.tagName == "INPUT" && o.type == "checkbox") {
__doPostBack("<%=UpdatePanel1.ClientID%>", "");
}
}
</script>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:TreeView ID="fcTreeView2" runat="server" ShowCheckBoxes="All" OnTreeNodeCheckChanged="fcTreeView2_TreeNodeCheckChanged" onclick="ClickTree()">
</asp:TreeView>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="fcTreeView2" EventName="TreeNodeCheckChanged" />
</Triggers>
</asp:UpdatePanel>
protected void fcTreeView2_TreeNodeCheckChanged(object sender, TreeNodeEventArgs e)
{
SetChildChecked(e.Node);
SetParentChecked(e.Node);
}
//遍历该节点,使其子节点状态与他保持一致
private void SetChildChecked(TreeNode parentNode)
{
foreach (TreeNode node in parentNode.ChildNodes)
{
node.Checked = parentNode.Checked;
SetChildChecked(node);
}
}
//看该结点有没有父节点
private void SetParentChecked(TreeNode childNode)
{
if (childNode.Parent != null)
{
childNode.Parent.Checked = childNode.Checked;
SetParentChecked(childNode.Parent);
}