客户端分页处理器


分页(查询)是客户端开发经常面临的问题.

经常性或者带有普遍性的问题, 好的对策是用抽象,而不是重复。
重复行为没有价值,而且有害,浪费资源(开发者资源,发布,运行时资源),代码臃肿,增加阅读和维护困难,弄不好牵一发而动全身。

程序的原始目的之一是把重复的事情交给系统自动完成,重复开发的结果是程序员在程序级别的同样行为。

当产生重复的冲动,需要ctrl+c/ctrl+v时,通常意味着结构性的提升机会出现,应该停下来去思考了,而不是去堆砌代码。
这种情况说明有被设计师忽略的事实,实际上对于一个非完全模式化有可因循的案例的系统,很难预见到一切.

通过实现分页处理器,可以简化客户端分页功能的开发。
在简化开发方面有以下参考原则:
.问自己能够再简化吗?
.通用不等于万能:清楚地认识能力和缺陷,不要强求

客户端在实现分页功能的场景如下:
在查询较大的数据量时,无法(也没有必要)一次全部获取结果,用户需要分次从服务器获取,浏览所关心的信息。
有价值的分页信息包括:总记录数,页数,当前页记录数.
用户可以通过界面控件在这些页之间导航,常用的有"下一页",下一页",到"首页",到"尾页",直接跳转到某页"Goto".

分页结果有几十页已经算是上限了,超过这个范围已经没有实际操作意义了,应该审视应用规划是否存在问题,如统计角度不实用。


使用分页处理器的步骤:
1.创建一个分页处理器
2.把分页处理器与控件绑定,设置页处理函数(页处理函数负责业务逻辑)
3.实现页处理函数


todo:
.按钮支持TLabel
.Goto支持:TEdit,TSpinEdit(TUpdown+TEdit)
.内部创建界面控件
.VCL组件化


*构造大型设备也是从零件入手,不要做成铁板一块的系统.
系统构造的几个要素是:组件,接口,活动机制(组件间协调)



头文件中声明分页处理器对象

#include "page_op.h"
//---------------------------------------------------------------------------
class TfrmGoodsResult : public TfrmBase1 {
    ///....
private:
    CPageOp<TSpeedButton> page_op_; ///< 分页操作对象

    int Query(unsigned int page_no);
};



实现文件中绑定控件,设置页处理函数
//---------------------------------------------------------------------------
void __fastcall TfrmGoodsResult::FormCreate(TObject *Sender)
{
    page_op_.SetControl(btFirst,btBack,btNext,btLast,cbPageNo);
    page_op_.SetAction(new CPageAction<TfrmGoodsResult>(this,&TfrmGoodsResult::Query));
}

//---------------------------------------------------------------------------
///< 页处理函数
///< 如:构造请求包向服务器请求
int TfrmGoodsResult::Query(unsigned int page_no) {
    CMsg *pMsg = new CMsg;
    pMsg->SetMsgType(umxns::MT_REQUEST);
    pMsg->SetMsgID(11127);
      
      /// 构造请求消息内容
        /// ...
        
    qry_cond_.page_no_ = page_no;
    CPagizeHelper::PutPageCond(pMsg,&qry_cond_);
    int result = 0;
    CMsg* pAns = 0;
    int ret = CBasePluginModule::sc_->call(pMsg, result,&pAns);
    if (ret||result)
        return -1;

    if (!CMsgHelper::CheckResult(pAns,0,1)) {
        pAns->Release();
        return -1;
    }

        ///< 处理返回消息
        ///....
        
    pAns->Release();

    return 0;
}

分页处理器定义如下:

文件:page_op.h

//---------------------------------------------------------------------------
class CPageActionBase {
public:
    virtual int Do(unsigned int page_no) = 0;
};

//---------------------------------------------------------------------------
///< 页活动类
///< 分页操作的活动内容
template <class T> class CPageAction : public CPageActionBase {
    typedef int (T::*PageActionFunc)(unsigned int page);
    T *obj_;
    PageActionFunc func_;
public:
    CPageAction(T *obj,PageActionFunc func):obj_(obj),func_(func) {
    }
    int Do(unsigned int page_no) {
        return (obj_->*func_)(page_no);
    }
};

//---------------------------------------------------------------------------
///< 分页操作类
template <class T> class CPageOp {
    unsigned int cur_page_; ///< 当前页号(页号从1开始)
    unsigned int page_count_; ///< 总页数

    T *first_;
    T *prev_;
    T *next_;
    T *last_;
    TComboBox *cbList_;

    unsigned int page_no_; ///< 输入的页号
    CVarValidator<unsigned int> page_no_validator_; ///< 输入页号校验器
    CIntValidator iv_; ///< 页号校验器

    CPageActionBase *action_;

    void UIControl_i();
public:
    CPageOp():page_count_(0),cur_page_(0),action_(0) {
        first_ = prev_ = next_ = last_ = 0;
        page_no_ = 0;
    }
    ~CPageOp() {
        if (action_) delete action_;
    }
    ///< 设置控件
    void SetControl(T *first,T *prev,T *next,T *last,TComboBox *cbList);

    void SetAction(CPageActionBase *action) {
        action_ = action;
    }
    void SetPageCount(unsigned int page_count);
    unsigned long GetPageCount() const { return page_count_; }

    void First(); ///< 第一页
    void Prev();  ///< 上一页
    void Next();  ///< 下一页
    void Last();  ///< 最后一页
    void GoTo(unsigned int page_no); ///< 转到page_no页

private:
    void __fastcall OnFirst(TObject *Sender);
    void __fastcall OnPrev(TObject *Sender);
    void __fastcall OnNext(TObject *Sender);
    void __fastcall OnLast(TObject *Sender);
    void __fastcall OnGoto(TObject *Sender);
};

#include "page_op.cpp"

page_op.cpp
//---------------------------------------------------------------------------
///< 设置控件
template <class T> void CPageOp<T>::SetControl(T *first,T *prev,T *next,T *last,TComboBox *cbList) {
    first_ = first;
    prev_ = prev;
    next_ = next;
    last_ = last;
    cbList_ = cbList;

    first_->OnClick = OnFirst;
    prev_->OnClick = OnPrev;
    next_->OnClick = OnNext;
    last_->OnClick = OnLast;
    cbList_->OnChange = OnGoto;

    first_->Enabled = false;
    prev_->Enabled = false;
    next_->Enabled = false;
    last_->Enabled = false;
//    cbList_->Style = csDropDownList;

    page_no_validator_.SetVar(&page_no_,ORM_FIELD_TYPE_INT,"页号");
    page_no_validator_.SetValidator(&iv_);
    page_no_validator_.BindControl(new CComboBox(cbList_));
}

//---------------------------------------------------------------------------
template <class T> void __fastcall CPageOp<T>::OnFirst(TObject *Sender) {
    First();
}
//---------------------------------------------------------------------------
template <class T> void __fastcall CPageOp<T>::OnPrev(TObject *Sender) {
    Prev();
}
//---------------------------------------------------------------------------
template <class T> void __fastcall CPageOp<T>::OnNext(TObject *Sender) {
    Next();
}
//---------------------------------------------------------------------------
template <class T> void __fastcall CPageOp<T>::OnLast(TObject *Sender) {
    Last();
}
//---------------------------------------------------------------------------
template <class T> void __fastcall CPageOp<T>::OnGoto(TObject *Sender) {
    int index = cbList_->ItemIndex;
    if (index!=-1) {
        GoTo(index+1);
    }
}

//---------------------------------------------------------------------------
template <class T> void CPageOp<T>::SetPageCount(unsigned int page_count) {
    page_count_ = page_count;

    if (page_count==0) {
        first_->Enabled = false;
        prev_->Enabled = false;
        next_->Enabled = false;
        last_->Enabled = false;
        cbList_->Clear();
        return;
    }
    for(int i=1;i<=page_count;i++)
        cbList_->Items->Add(String(i));

    iv_.SetMinValue(1);
    iv_.SetMaxValue(page_count_);
}
//---------------------------------------------------------------------------
template <class T> void CPageOp<T>::First() {
    if (action_->Do(1)) {
        return;
    }

    cur_page_ = 1;
    UIControl_i();
}

//---------------------------------------------------------------------------
template <class T> void CPageOp<T>::Prev() {
    if (action_->Do(cur_page_-1)) {
        return;
    }
   cur_page_--;
   UIControl_i();
}

//---------------------------------------------------------------------------
template <class T> void CPageOp<T>::Next() {
    if (action_->Do(cur_page_+1)) {
        return;
    }
   cur_page_++;
   UIControl_i();
}

//---------------------------------------------------------------------------
template <class T> void CPageOp<T>::Last() {
    if (action_->Do(page_count_)) {
        return;
    }
    cur_page_ = page_count_;
    UIControl_i();
}

//---------------------------------------------------------------------------
template <class T> void CPageOp<T>::UIControl_i() {
   cbList_->ItemIndex = cur_page_-1;
   first_->Enabled = cur_page_!=1;
   prev_->Enabled = cur_page_!=1;
   next_->Enabled = cur_page_!=page_count_;
   last_->Enabled = cur_page_!=page_count_;
}

//---------------------------------------------------------------------------
template <class T> void CPageOp<T>::GoTo(unsigned int page_no) {
    if (action_->Do(page_no)) {
        return;
    }
    cur_page_ = page_no;
    UIControl_i();
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值