Winform開發(fā)框架之肖像顯示保存控件的實(shí)現(xiàn)

我們?cè)陂_發(fā)一些Winform程序的時(shí)候叙量,除了常規(guī)的顯示普通數(shù)據(jù)外,有的時(shí)候需要顯示一些人員肖像或者一些車輛等物體的圖片九串,一般這些內(nèi)容較小,所以以二進(jìn)制存儲(chǔ)在數(shù)據(jù)庫(kù)是一個(gè)不錯(cuò)的方案寺鸥。但由于它們雖然很常用猪钮,設(shè)計(jì)數(shù)據(jù)庫(kù)保存的邏輯又會(huì)使得整個(gè)控件的封裝顯得麻煩很多。本文介紹的肖像顯示保存控件胆建,通過事件的封裝處理烤低,讓數(shù)據(jù)的保存不在依賴于數(shù)據(jù)庫(kù)存儲(chǔ)模塊,實(shí)現(xiàn)更加通用的特性笆载。

1扑馁、肖像顯示保存控件的需求

我們?cè)谝恍┏绦蛄死锩妫赡苄枰@示一些人員頭像凉驻,車輛圖片腻要,物件圖片等,這些圖片可以從電腦上選取涝登,也可以拍照雄家,當(dāng)然最重要的是,方便使用胀滚,并能存儲(chǔ)到數(shù)據(jù)庫(kù)里面趟济,這個(gè)就是我們一般的需求了乱投。
1)人員肖像顯示效果:



2)車輛圖片展示效果



控件的工具條上,提供了編輯圖片顷编,保存圖片戚炫,恢復(fù)默認(rèn)圖片,拍照等功能媳纬,當(dāng)然我們希望控件和整個(gè)界面一起双肤,實(shí)現(xiàn)圖片數(shù)據(jù)的方便加載和保存操作。

2层宫、肖像顯示保存控件的設(shè)計(jì)

前面我們看了一些常用的場(chǎng)景杨伙,對(duì)我們?cè)O(shè)計(jì)這個(gè)通用性的肖像顯示保存控件有很好的指導(dǎo)意義,我們只需要把圖片顯示部分作為一個(gè)控件萌腿,然后公布一些事件給外部實(shí)現(xiàn)限匣,從而實(shí)現(xiàn)我們需要的數(shù)據(jù)加載、數(shù)據(jù)保存等操作毁菱,至于其他的功能米死,我們可以集成到里面去。
我們?cè)O(shè)計(jì)一個(gè)用戶自定義控件贮庞,上面放一個(gè)圖片顯示框峦筒,然后增加一些按鈕在上面,并設(shè)置好工具欄的圖片顯示窗慎,效果如下所示物喷。



由于我們需要給外部處理數(shù)據(jù)的綁定(需要從數(shù)據(jù)庫(kù)加載)和數(shù)據(jù)的保存(保存到數(shù)據(jù)庫(kù)里面),因此拋出兩個(gè)委托代理定義遮斥。

/// <summary>
/// 保存圖片的處理代理定義
/// </summary>
/// <param name="id">記錄ID</param>
/// <param name="imageBytes">圖片數(shù)據(jù)</param>
/// <param name="imageType">圖片類型</param>
/// <returns></returns>
public delegate bool SavePortraitHandler(string id, byte[] imageBytes, string imageType);

/// <summary>
/// 綁定圖片數(shù)據(jù)的代理定義
/// </summary>
/// <param name="id">記錄ID</param>
/// <param name="imageType">圖片類型</param>
/// <returns></returns>
public delegate byte[] BindPortraitHandler(string id, string imageType);

然后我們?cè)谟脩艨丶锩嬖黾右恍傩院褪录x峦失,部分代碼如下所示。

/// <summary>
/// 圖片數(shù)據(jù)顯示和采集控件
/// </summary>
public partial class PortraitControl : XtraUserControl
{
    #region 事件及屬性定義
    /// <summary>
    /// 保存圖片操作的事件
    /// </summary>
    public event SavePortraitHandler OnSavePortrait;

    /// <summary>
    /// 綁定圖片數(shù)據(jù)的事件
    /// </summary>
    public event BindPortraitHandler OnBindPortait;

    /// <summary>
    /// 記錄ID
    /// </summary>
    public string ID { get; set; }

    /// <summary>
    /// 圖片是否被修改過
    /// </summary>
    public bool ImageIsDirty { get; set; }

然后我們需要實(shí)現(xiàn)的就是术吗,公布兩個(gè)公共方法尉辑,分別是數(shù)據(jù)的綁定,綁定到界面控件的操作函數(shù)较屿,我們主要注意的是隧魄,這里調(diào)用了事件OnBindPortait,以實(shí)現(xiàn)數(shù)據(jù)庫(kù)的解耦隘蝎,代碼如下所示购啄。

/// <summary>
/// 綁定圖片的操作,觸發(fā)綁定事件處理
/// </summary>
/// <param name="id">記錄ID</param>
public void BindPicture(string id)
{
    try
    {
        this.ID = id; //設(shè)置控件的ID值

        #region 更新圖片顯示操作

        if (OnBindPortait == null)
        {
            MessageDxUtil.ShowTips("控件未指定OnBindPortait事件處理");
            return;
        }

        byte[] imageBytes = OnBindPortait(id, ImageType);
        if (imageBytes != null)
        {
            this.picPortrait.Image = ImageHelper.ImageFromBytes(imageBytes);
        }
        else
        {
            ResetDefaultImage(ImageType);
        }

        #endregion
    }
    catch (Exception ex)
    {
        MessageDxUtil.ShowError(ex.Message);
        LogTextHelper.Error(ex);
    }
}

數(shù)據(jù)庫(kù)保存的實(shí)現(xiàn)末贾,和上面思路差不多闸溃,也是實(shí)現(xiàn)事件的處理即可,通過調(diào)用事件OnSavePortrait,實(shí)現(xiàn)數(shù)據(jù)庫(kù)的解耦辉川。

/// <summary>
/// 保存圖片到服務(wù)器
/// </summary>
public bool SavePicture(string id)
{
    this.ID = id;//設(shè)置控件的ID值

    if (string.IsNullOrEmpty(id))
    {
        MessageDxUtil.ShowTips("記錄ID未指定表蝙,無(wú)法保存,請(qǐng)先保存數(shù)據(jù)乓旗!");
        return false;
    }
    if (OnSavePortrait == null)
    {
        MessageDxUtil.ShowTips("控件未指定OnSavePortrait處理事件府蛇!");
        return false;
    }

    if (picPortrait.Image != null)
    {
        try
        {
            byte[] imageBytes = ImageHelper.ImageToBytes(this.picPortrait.Image);

            bool sucess = false;
            if (OnSavePortrait != null)
            {
                sucess = OnSavePortrait(this.ID, imageBytes, ImageType);
            }
            return sucess;

        }
        catch (Exception ex)
        {
            MessageDxUtil.ShowError(ex.Message);
            LogTextHelper.Error(ex);
        }
    }
    return false;
}

3、肖像顯示保存控件的使用

完成以上控件的設(shè)計(jì)和處理后屿愚,編譯后汇跨,模塊將增加一個(gè)用戶控件,這樣我們就可以在需要的界面模塊里面妆距,把這個(gè)控件拖動(dòng)到設(shè)計(jì)界面里面去了穷遂,設(shè)計(jì)效果和下圖類似。



這個(gè)時(shí)候娱据,肖像顯示保存控件就作為一個(gè)整體進(jìn)行使用了蚪黑。
由于我們?cè)O(shè)計(jì)控件的時(shí)候,我們把它和外部數(shù)據(jù)庫(kù)存儲(chǔ)和加載進(jìn)行了隔離中剩,因此這里需要進(jìn)行整合忌穿,通過事件進(jìn)行整合處理。調(diào)用代碼如下所示结啼。

public partial class FrmEditDriver : BaseEditForm
{
    public FrmEditDriver()
    {
        InitializeComponent();

        this.portraitControl1.ImageType = "個(gè)人肖像";
        this.portraitControl1.OnBindPortait += new BindPortraitHandler(portraitControl1_OnBindPortait);
        this.portraitControl1.OnSavePortrait += new SavePortraitHandler(portraitControl1_OnSavePortrait);
    }

然后實(shí)現(xiàn)其中自動(dòng)增加的事件函數(shù)即可掠剑,主要就是調(diào)用業(yè)務(wù)類實(shí)現(xiàn)數(shù)據(jù)的存儲(chǔ)和加載處理邏輯,代碼如下所示郊愧。

bool portraitControl1_OnSavePortrait(string id, byte[] imageBytes, string imageType)
{
    return BLLFactory<Driver>.Instance.UpdateImageBytes(id, imageBytes, imageType);
}

byte[] portraitControl1_OnBindPortait(string id, string imageType)
{
    return BLLFactory<Driver>.Instance.GetImageBytes(id, imageType);
}

在數(shù)據(jù)的顯示函數(shù)里面朴译,我們主動(dòng)調(diào)用控件的函數(shù)實(shí)現(xiàn)界面數(shù)據(jù)的綁定顯示。

/// <summary>
/// 數(shù)據(jù)顯示的函數(shù)
/// </summary>
public override void DisplayData()
{
    InitDictItem();//數(shù)據(jù)字典加載(公用)

    if (!string.IsNullOrEmpty(ID))
    {
        #region 顯示信息
        DriverInfo info = BLLFactory<Driver>.Instance.FindByID(ID);
        if (info != null)
        {
            tempInfo = info;//重新給臨時(shí)對(duì)象賦值属铁,使之指向存在的記錄對(duì)象

            txtHandNo.Text = info.HandNo;
            txtName.Text = info.Name;
            txtMobile.Text = info.Mobile;
            txtDept.Text = info.Dept;
            txtStartDriveDate.SetDateTime(info.StartDriveDate);
            txtSex.Text = info.Sex;
            txtBirthday.SetDateTime(info.Birthday);
            txtNote.Text = info.Note;
        }
        #endregion
    }
    else
    {
    }

    //綁定圖片
    this.portraitControl1.BindPicture(tempInfo.ID);
}

而在保存按鈕實(shí)現(xiàn)數(shù)據(jù)保存的時(shí)候动分,我們也可以調(diào)用控件自身的保存操作函數(shù),實(shí)現(xiàn)數(shù)據(jù)的存儲(chǔ)红选。

/// <summary>
/// 新增狀態(tài)下的數(shù)據(jù)保存
/// </summary>
/// <returns></returns>
public override bool SaveAddNew()
{
    DriverInfo info = tempInfo;//必須使用存在的局部變量,因?yàn)椴糠中畔⒖赡鼙桓郊褂?    SetInfo(info);

    try
    {
        #region 新增數(shù)據(jù)

        bool succeed = BLLFactory<Driver>.Instance.Insert(info);
        if (succeed)
        {
            //可添加其他關(guān)聯(lián)操作
            this.portraitControl1.SavePicture(tempInfo.ID);

            return true;
        }
        #endregion
    }
    catch (Exception ex)
    {
        LogTextHelper.Error(ex);
        MessageDxUtil.ShowError(ex.Message);
    }
    return false;
}

通過和數(shù)據(jù)庫(kù)操作實(shí)現(xiàn)解耦姆另,我們可以對(duì)這個(gè)控件進(jìn)行更方便的重用喇肋,而代碼也很簡(jiǎn)單,這樣也就實(shí)現(xiàn)了我們統(tǒng)一化迹辐、簡(jiǎn)單化蝶防、可復(fù)用性的目標(biāo)了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末明吩,一起剝皮案震驚了整個(gè)濱河市间学,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖低葫,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件详羡,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡嘿悬,警方通過查閱死者的電腦和手機(jī)实柠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來善涨,“玉大人窒盐,你說我怎么就攤上這事「峙。” “怎么了蟹漓?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)源内。 經(jīng)常有香客問我葡粒,道長(zhǎng),這世上最難降的妖魔是什么姿锭? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任塔鳍,我火速辦了婚禮,結(jié)果婚禮上呻此,老公的妹妹穿的比我還像新娘轮纫。我一直安慰自己,他們只是感情好焚鲜,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布掌唾。 她就那樣靜靜地躺著,像睡著了一般忿磅。 火紅的嫁衣襯著肌膚如雪糯彬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天葱她,我揣著相機(jī)與錄音撩扒,去河邊找鬼。 笑死吨些,一個(gè)胖子當(dāng)著我的面吹牛搓谆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播豪墅,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼泉手,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了偶器?” 一聲冷哼從身側(cè)響起斩萌,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤缝裤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后颊郎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體憋飞,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年袭艺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了搀崭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡猾编,死狀恐怖瘤睹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情答倡,我是刑警寧澤轰传,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站瘪撇,受9級(jí)特大地震影響获茬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜倔既,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一恕曲、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧渤涌,春花似錦佩谣、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至安皱,卻和暖如春调鬓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背酌伊。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工腾窝, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人居砖。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓燕锥,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親悯蝉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 一托慨、簡(jiǎn)歷準(zhǔn)備 1鼻由、個(gè)人技能 (1)自定義控件、UI設(shè)計(jì)、常用動(dòng)畫特效 自定義控件 ①為什么要自定義控件蕉世? Andr...
    lucas777閱讀 5,206評(píng)論 2 54
  • 撐著油紙傘 獨(dú)自彷徨在悠長(zhǎng)狠轻、悠長(zhǎng)又寂寥的雨巷 我希望逢著 一個(gè)丁香一樣的 結(jié)著愁怨的姑娘 辦公室窗前有一顆丁...
    文雖刀閱讀 1,315評(píng)論 3 10
  • 運(yùn)行APP的時(shí)候提示 [App] if we're in the real pre-commit handler ...
    那片飄落的樹葉閱讀 296評(píng)論 0 0
  • 剛剛無(wú)意間看到了一個(gè)朋友的婚紗照奸例,我在想,他們?cè)谝黄鹞迥臧胂蚵ィ液驮?jīng)的那個(gè)他也是五年半查吊,為什么他們結(jié)婚了,我們卻天...
    我是三七閱讀 106評(píng)論 0 0
  • 第一天通過親子時(shí)間管理課程第一天的學(xué)習(xí)湖蜕,從為什么要學(xué)習(xí)親子時(shí)間管理和孩子時(shí)間管理管什么這兩個(gè)角度逻卖,來解決孩子沒...
    Abby愛整理閱讀 183評(píng)論 0 2