Burnett

淡定,执着......
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

使用Web部件连接接口实现可以设置条件的过滤器

Posted on 2007-03-22 15:46  Burnett  阅读(1694)  评论(1编辑  收藏  举报
  在MOSS2007企业版里,默认提供了很多的过滤器,但是没有一种过滤器可以实现事先设定过滤条件,比如选择当前列表栏作为筛选条件,然后输入对应值,为了满足需求,使用了IFilterProvider接口实现一个Web部件。
   可以实现的功能:
   可以实现多条件候选值下的单一条件过滤。
   可以根据当前连接部件的视图自动适应栏,不需要使用者自己干预。

   前期的知识准备:
   需要有基本的Web部件的制作部署知识,需要了解Web部件连接的知识背景,这点在WSS SDK里写的很清楚,这个Web部件也是基于SDK写出来的。
   MOSS2007使用了新的接口,所以老的接口不在赞成使用,并且编译过程中会出现如下警告:
警告    18    “Microsoft.SharePoint.WebPartPages.Communication.ClearFilterEventHandler”已过时:“Use System.Web.UI.WebControls.WebParts.IWebPartParameters instead”    F:\毕业设计资料\Codes\Web Part1\Web Part1\SqlFilter\Sample.cs    31    46    Web Part1

但是本文为了兼容性,还是使用了老的接口版本。标准的IFilterProvider必须继承6个接口,但是有一些接口是可选的,所以我在这里省却一个。

using System;
using System.IO;
using System.Text;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml.Serialization;

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using Microsoft.SharePoint.WebPartPages.Communication;

namespace MyCompany.Management.Employees
{
    [Guid(
"990c2459-2ec6-4794-931d-1e1a67acd723")]
    
public class SqlFilter :WebPart, IFilterProvider
    {
        
#region Web控件
        
private DropDownList ddl;
        
private Button btn_setfilter;
        
private Label lb_msg;
        
private TextBox tb_input;
        
private Button btn_clearfilter;
        
#endregion
        
#region 控制变量
        
private bool isConnected;
        
private string consumername;
        
private bool isClearFilterClicked;
        
private bool isSetFilterClicked;
        
private string errormsg;
        
/// <summary>
        
/// 存储列表的域,也就是数据库表中的列
        
/// </summary>
        private string[] fieldList=null;
        
/// <summary>
        
/// 存储列表域的显示名称
        
/// </summary>
        private string[] fielddspList=null;

        
/// <summary>
        
/// 下拉列表设定的过滤条件
        
/// </summary>
        private string filtercondition=string.Empty;

        
/// <summary>
        
/// 过滤条件表达式
        
/// </summary>
        private string filterExp;

        
/// <summary>
        
/// 保存域的视图状态
        
/// </summary>
        private string dropdownlistVK="FieldsList";
        
#endregion
        
#region IFilterProvider事件
        
/// <summary>
        
/// FilterProvider的事件
        
/// </summary>
        public event SetFilterEventHandler SetFilter;
        
public event NoFilterEventHandler NoFilter;
        
public event ClearFilterEventHandler ClearFilter;
        
#endregion
        
#region 重写的接口方法
        
/// <summary>
        
/// 注册窗体
        
/// </summary>
        public override void EnsureInterfaces()
        {
            
try
            {
                
//功能类似于win32中的窗体注册
                RegisterInterface("myFilterProvider",
                    InterfaceTypes.IFilterProvider,
                    WebPart.LimitOneConnection,
                    ConnectionRunAt.Server,
                    
this"""将过滤器提供给""过滤器"true);
            }
            
catch (Exception ee)
            {
                errormsg 
= ee.ToString();
                WriteLog(ee.ToString());
            }
        }

        
/// <summary>
        
/// 重写CanRunat方法
        
/// 在web part被重写之前通知asp.net基础结构
        
/// 检查欲重写的web part是否可以运行在当前配置之上
        
/// </summary>
        
/// <returns></returns>
        public override ConnectionRunAt CanRunAt()
        {
            
return ConnectionRunAt.Server;
        }

        
/// <summary>
        
/// 获得Consumer一端的信息,
        
/// 通知此web part在预重写阶段
        
/// 已连接。
        
/// 
        
/// </summary>
        
/// <param name="interfaceName">指定的接口名称和RegisterInterface
        
/// 中的名称保持一致</param>
        
/// <param name="connectedPart">连接上的web part</param>
        
/// <param name="connectedInterfaceName"></param>
        
/// <param name="runAt"></param>
        public override void PartCommunicationConnect(string interfaceName, 
            Microsoft.SharePoint.WebPartPages.WebPart connectedPart,
            
string connectedInterfaceName,
            ConnectionRunAt runAt)
        {
            
try
            {
                
if (interfaceName == "myFilterProvider")
                {
                    isConnected 
= true;
                    consumername 
= connectedPart.Title;
                }
            }
            
catch (Exception ee)
            {
                lb_msg.Text 
= ee.ToString();
                WriteLog(ee.ToString());
            }

        }



        
/// <summary>
        
/// 通信的主要展开点
        
/// 在这里可以触发
        
/// SetFilter
        
/// NoFilter
        
/// ClearFilter
        
/// 事件,可以按照需要来选择。
        
/// </summary>
        public override void PartCommunicationMain()
        {
            
int i = 0;
            EnsureChildControls();
            
try
            {
                
if (isConnected)
                {
                    
//在这里设置过滤条件
                    
//过滤条件的格式为
                    
//"FieldLabel"+{1.n}+"="+列名+"&"+"FieldValue"+{1.n}+"="+列值
                    if (SetFilter != null && isSetFilterClicked)
                    {
                        
//匹配列
                        
                        
if (fieldList.Length == 0)
                            lb_msg.Text 
= "列数为0,不能筛选";
                        
else
                        
for (; i < fieldList.Length; i++)
                            
if (fielddspList[i] == ddl.SelectedItem.Text)
                                
break;
                            
                        
if (tb_input.Text != null)
                            filterExp 
= "FilterField1" + "=" + fieldList[i] +
                            
"&" +
                            
"FilterValue1" + "=" + tb_input.Text;

                        SetFilterEventArgs sea 
= new SetFilterEventArgs();
                        sea.FilterExpression 
= filterExp;
                        SetFilter(
this, sea);

                    }
                    
else if (ClearFilter != null && isClearFilterClicked)
                    {
                        ClearFilter(
thisnew EventArgs());
                        isClearFilterClicked 
= false;

                        
for (i = 0; i < fieldList.Length; i++)
                            fieldList[i] 
= fielddspList[i] = String.Empty;
                    }
                    
else
                        
if (NoFilter != null)
                            NoFilter(
thisnew EventArgs());
                }
            }
            
catch (Exception ee)
            {
                lb_msg.Text
=ee.ToString()+" ||  当前的i值"+i;
                WriteLog(ee.ToString());
            }
        }

        
/// <summary>
        
/// 这个事件由Consumer的PartCommunicationInit触发,
        
/// 作用是 接受由Consumer可能发出的一些参数列表,比如列表的栏名和显示名
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="filterConsumerInitEventArgs"></param>
        public void FilterConsumerInit(object sender,
           FilterConsumerInitEventArgs filterConsumerInitEventArgs)
        {
            
if (filterConsumerInitEventArgs.FieldList != null)
                fieldList 
= filterConsumerInitEventArgs.FieldList;
            
else
                fieldList 
= null;
            
if (filterConsumerInitEventArgs.FieldDisplayList != null)
                fielddspList 
= filterConsumerInitEventArgs.FieldDisplayList;
            
else
                fielddspList 
= null;
            
if(ddl!=null)
                
if (ddl.Items.Count == 0 && fieldList != null)
                {
                    
for (int i = 0; i < fieldList.Length; i++)
                        ddl.Items.Add(
new ListItem(fielddspList[i], fieldList[i]));
                }

        }

        
#endregion
        
protected override void RenderWebPart(HtmlTextWriter output)
        {
            
if (!isConnected)
                output.Write(
"请选择一个列表作为Consumer!");
            
else
            {
                
if (ddl.Items.Count == 0 && fieldList != null)
                {
                    
for (int i = 0; i < fieldList.Length; i++)
                        ddl.Items.Add(
new ListItem(fielddspList[i], fieldList[i]));
                }
                ddl.RenderControl(output);
                tb_input.RenderControl(output);
                btn_setfilter.RenderControl(output);
                lb_msg.RenderControl(output);
                btn_clearfilter.RenderControl(output);
            }
        }

        
protected override void CreateChildControls()
        {
            ddl 
= new DropDownList();
            ddl.AutoPostBack 
= true;
            ddl.ID 
= "ddl";
            btn_setfilter 
= new Button();
            btn_clearfilter 
= new Button();
            btn_clearfilter.Text 
= "清除结果";
            lb_msg 
= new Label();

            
//if (ViewState[dropdownlistVK] == null && fieldList.Length != 0)
            
//{
            
//    string dropdown = ViewState[dropdownlistVK];
            
//    for (int i = 0; i < fieldList.Length; i++)
            
//    {
            
//        ddl.Items.Add(new ListItem(fielddspList[i], fieldList[i]));
            
//        if (i < fieldList.Length - 1)
            
//            ViewState[dropdownlistVK] += ddl.Items[i].Value;
            
//    }
            
//}

            btn_setfilter.Click 
+= new EventHandler(btn_Click);
            btn_clearfilter.Click 
+= new EventHandler(btn_clearfilter_Click);
            ddl.SelectedIndexChanged 
+= new EventHandler(ddl_SelectedIndexChanged);
            tb_input 
= new TextBox();

            
//设置文本框响应回车事件
            tb_input.Attributes.Add("onkeypress","<script   language='javascript'>document.all."+tb_input.ClientID+".click;</script>");
            btn_setfilter.Text 
= "提交";
            Controls.Add(ddl);     
            Controls.Add(tb_input);
            Controls.Add(btn_setfilter);
            Controls.Add(btn_clearfilter);
            Controls.Add(lb_msg);
        }

        
void btn_clearfilter_Click(object sender, EventArgs e)
        {
            isClearFilterClicked 
= true;
        }

        
void btn_Click(object sender, EventArgs e)
        {
            isSetFilterClicked 
= true
        }


        
void ddl_SelectedIndexChanged(object sender, EventArgs e)
        {
            filtercondition
= ddl.SelectedItem.Text;
        }

        
private void WriteLog(string log)
        {
            
string path = @"/log.txt";
            
if (!File.Exists(path))
            
using (StreamWriter sw= File.CreateText(path))
            {
                sw.Write(String.Format(
"{0}:    {1}",DateTime.Now,log));
            }

            
using (StreamWriter sw=File.AppendText(path))
            {
                sw.Write(String.Format(
"{0}:    {1}", DateTime.Now, log));
            }
            
        }
    }
}

书写注意事项:
实现CreateChildControls如要重写RenderWebpart方法,需要在RenderWebpart中重新使用HtmlTextWriter输出,否则RenderWebpart会覆盖掉CreateChildControls方法输出的控件。
注意Provider连接Consumer的不同阶段,否则在创建控件输出的时候会出现问题。
因为有时候Web部件不会输出你的错误(这些错误往往是在创建用户控件的时候),最好可以写一个日志文件,便于查错。
必须要实现NoFilter事件,否则Web部件会报错,提示连接数过多,这和RegisterInterface函数中的连接数没有关系。

这里是使用效果截图:
过滤条件将会自动适应视图中的栏