Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 最近中文字幕完整版视频1,久久久久久免费视频,日韩毛片大全

          整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          金蝶云星空插件實(shí)戰(zhàn)開發(fā)-服務(wù)插件-自定義校驗(yàn)方法

          金蝶云星空插件實(shí)戰(zhàn)開發(fā)-服務(wù)插件-自定義校驗(yàn)方法

          文為金蝶云星空自定義校驗(yàn)方法的新手教程。內(nèi)容為技術(shù)類文章。做星空系統(tǒng)二次開發(fā)的新手朋友,可以收藏作為參考。非技術(shù)職業(yè)的朋友,可以直接劃走,以免耽誤您的寶貴時(shí)間。

          閱讀對(duì)象:星空系統(tǒng)二次開發(fā)新手
          需求場(chǎng)景:在插件開發(fā)過程中,實(shí)現(xiàn)BOS不容易配置的單據(jù)數(shù)據(jù)校驗(yàn)。實(shí)現(xiàn)校驗(yàn)一個(gè)單據(jù)編號(hào)字段必須是11個(gè)字符。
          開發(fā)語(yǔ)言:C#
          開發(fā)工具:Visual Studio 2019
          星空版本:7.6.0

          說明:本文前提是開發(fā)機(jī)已經(jīng)安裝好金蝶云星空系統(tǒng)和金蝶BOS IDE。

          金蝶云社區(qū)課程詳情-課程詳情-金蝶云社區(qū)官網(wǎng)

          本文是承接“金蝶云星空插件實(shí)戰(zhàn)開發(fā)-服務(wù)插件”這篇教程。是在這篇教程的基礎(chǔ)上做的擴(kuò)展。

          如果想要測(cè)試本文的代碼,必須順利完成服務(wù)插件的教程。

          打開服務(wù)插件的代碼項(xiàng)目,在Visual Studio右側(cè)的“解決方案資源管理器”中郵件點(diǎn)擊服務(wù)插件工程,新建一個(gè)類,類名:PurchaseValidator.cs,如下圖所示:

          既然創(chuàng)建的一個(gè)類文件,那下面就直接敲代碼咯,代碼如下:

          using System;
          using Kingdee.BOS;
          using Kingdee.BOS.Core;
          using Kingdee.BOS.Core.Validation;
          
          namespace Test.K3Cloud.SCM.MyAppPlugin
          {
              public class PurchaseValidator : AbstractValidator
              {
                  /// <summary>
                  /// 初始化
                  /// </summary>
                  /// <param name="validateContext"></param>
                  /// <param name="ctx"></param>
                  public override void InitializeConfiguration(ValidateContext validateContext, Context ctx)
                  {
                      base.InitializeConfiguration(validateContext, ctx);
          
                      if (validateContext.BusinessInfo !=null)
                      {
                          EntityKey=validateContext.BusinessInfo.GetEntity(0).Key;
                      }
                  }
          
                  /// <summary>
                  /// 自定義校驗(yàn)
                  /// </summary>
                  /// <param name="dataEntities"></param>
                  /// <param name="validateContext"></param>
                  /// <param name="ctx"></param>
                  public override void Validate(ExtendedDataEntity[] dataEntities, ValidateContext validateContext, Context ctx)
                  {
                      if (validateContext.IgnoreWarning)
                      {
                          return; //警告已經(jīng)被用戶忽略,就不需要再次執(zhí)行了
                      }
          
                      if (dataEntities==null || dataEntities.Length <=0)
                      {
                          return;
                      }
          
                      // 循環(huán)校驗(yàn)每一個(gè)數(shù)據(jù)包(一個(gè)數(shù)據(jù)包對(duì)應(yīng)一張單據(jù))
                      foreach (var et in dataEntities)
                      {
                          // 訂單編號(hào)在單據(jù)數(shù)據(jù)包中的字段名為:BillNo
                          string billNo=Convert.ToString(et.DataEntity["BillNo"]);
                          if (billNo.Length !=11)
                          {
                              validateContext.AddError(et, new ValidationErrorInfo(
                                 "BillNo",                                        // 出錯(cuò)的字段Key,可以空
                                 Convert.ToString(et.DataEntity[0]),              // 數(shù)據(jù)包內(nèi)碼,必填,后續(xù)操作會(huì)據(jù)此內(nèi)碼避開此數(shù)據(jù)包
                                 et.DataEntityIndex,                              // 出錯(cuò)的數(shù)據(jù)包在全部數(shù)據(jù)包中的順序
                                 et.RowIndex,                                     // 出錯(cuò)的數(shù)據(jù)行在全部數(shù)據(jù)行中的順序,如果校驗(yàn)基于單據(jù)頭,此為0
                                 "Error 0",                                       // 錯(cuò)誤編碼,可以任意設(shè)定一個(gè)字符,主要用于追查錯(cuò)誤來源
                                 "數(shù)據(jù)校驗(yàn)未通過,單據(jù)編號(hào)必須是11個(gè)字符",        // 錯(cuò)誤的詳細(xì)提示信息
                                 "單據(jù)合法性檢查",                                // 錯(cuò)誤的簡(jiǎn)明提示信息
                                 ErrorLevel.FatalError                            // 錯(cuò)誤級(jí)別
                              ));
                          }
                      }
                  }
              }
          }

          自定義校驗(yàn)器類需要繼承 AbstractValidator 類。

          在自定義校驗(yàn)器類中,dataEntities 為客戶端傳遞過來的單據(jù)的數(shù)據(jù)。

          可以多個(gè)單據(jù)同時(shí)操作,所以這里,單據(jù)數(shù)據(jù)是一個(gè)數(shù)組。

          上面代碼中 et.DataEntity 是某個(gè)單據(jù)的數(shù)據(jù)包。

          接下來我們?cè)诜?wù)插件中注冊(cè)自定義校驗(yàn)器。

          為了方便大家順利閱讀代碼,下面將服務(wù)插件的完整代碼貼出來。

          如下面代碼所示:

          using System;
          using System.Collections.Generic;
          using System.Linq;
          using System.Text;
          
          using Kingdee.BOS;
          using Kingdee.BOS.Core.DynamicForm;
          using Kingdee.BOS.Core.DynamicForm.PlugIn;
          using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
          using Kingdee.BOS.Core.Interaction;
          using Newtonsoft.Json.Linq;
          
          namespace Test.K3Cloud.SCM.MyAppPlugin
          {
              public class Class1: AbstractOperationServicePlugIn
              {
                  // SpensorKey
                  private const string SpensorKey="DefaultSpensorKey";
          
                  /// <summary>
                  /// 單據(jù)校驗(yàn)。
                  /// </summary>
                  /// <param name="e"></param>
                  public override void OnAddValidators(AddValidatorsEventArgs e)
                  {
                      base.OnAddValidators(e);
          
                      var purchaseValidator=new PurchaseValidator();
                      e.Validators.Add(purchaseValidator);    // 注冊(cè)自定義校驗(yàn)器
                  }
          
                  public override void EndOperationTransaction(EndOperationTransactionArgs e)
                  {
                      base.EndOperationTransaction(e);
          
                      // 當(dāng)保存訂單時(shí)
                      if (FormOperation.OperationName=="保存")
                      {
                          /// 構(gòu)造錯(cuò)誤信息
                          JArray errMsg=new JArray {
                              new JValue("01"),
                              new JValue("這是一條提示信息")
                          };
          
                          bool ignore=false;    // 窗口顯示狀態(tài),默認(rèn)不顯示
                          Option.TryGetVariableValue(SpensorKey, out ignore);
                          if (!ignore && !Option.HasInteractionFlag(SpensorKey))
                          {
                              KDInteractionException ie=ShowErrorMsg(Context, SpensorKey, ignore, errMsg);
                              throw ie;
                          }
                      }
                  }
          
                  /// <summary>
                  /// 信息提示窗口
                  /// </summary>
                  /// <param name="context">上下文對(duì)象</param>
                  /// <param name="spensorKey">窗口標(biāo)識(shí)</param>
                  /// <param name="ignore">狀態(tài)</param>
                  /// <param name="errorMsg">錯(cuò)誤信息</param>
                  /// <returns></returns>
                  public static KDInteractionException ShowErrorMsg(Context context, string spensorKey, bool ignore, JArray errorMsg)
                  {
                      if (errorMsg.Count() !=2)
                      {
                          return null;
                      }
          
                      string titleMsg="代碼~|~信息";
                      string errMsg="{0}~|~{1}";
                      K3DisplayerModel model=K3DisplayerModel.Create(context, titleMsg);
                      model.AddMessage(string.Format(errMsg, errorMsg[0].ToString(), errorMsg[1].ToString()));
                      model.Option.SetVariableValue(K3DisplayerModel.CST_FormTitle, "單據(jù)操作有以下信息出錯(cuò),需要繼續(xù)嗎?");
                      model.OKButton.Caption=new LocaleValue("是");
                      model.CancelButton.Visible=model.OKButton.Visible=true;
                      model.CancelButton.Caption=new LocaleValue("否");
                      KDInteractionException ie=new KDInteractionException(spensorKey);
                      ie.InteractionContext.InteractionFormId="BOS_K3Displayer";
                      ie.InteractionContext.K3DisplayerModel=model;
                      ie.InteractionContext.IsInteractive=true;
                      return ie;
                  }
              }
          }

          我們?cè)?OnAddValidators 方法中注冊(cè)自定義校驗(yàn)器。

          到此,自定義校驗(yàn)器最基本的代碼就完成了。

          當(dāng)然了,本文的校驗(yàn)只是做演示用,大家根據(jù)實(shí)際需求,做具體的校驗(yàn)。

          敲完代碼,我們編譯插件。編譯插件的方法,金蝶云星空插件實(shí)戰(zhàn)開發(fā)-新手入門教程-服務(wù)插件這篇教程里有描述,這里就不做重復(fù)說明了。

          插件編譯完成之后,重啟IIS服務(wù)。然后測(cè)試效果,如下圖所示:

          如果一次沒有成功,沒關(guān)系,萬事開頭難,大家跟著做多做幾次,希望本教程能夠幫助到大家!加油?。?/span>

          本教程源碼:

          https://gitee.com/hsg4ok_admin/kingdee_documents/tree/master/%E7%A4%BA%E4%BE%8B%E4%BB%A3%E7%A0%81/Test.K3Cloud.SCM.MyAppPlugin


          更多精彩內(nèi)容發(fā)布于公眾號(hào):代碼乾坤 (CoderLand)

          個(gè)Hook讓你體驗(yàn)極致舒適的Dialog使用方式!

          Dialog地獄

          為啥是地獄?

          因?yàn)榉彩怯蠨ialog出現(xiàn)的頁(yè)面,其代碼絕對(duì)優(yōu)雅不起來!因?yàn)橐坏┠阍谝矀€(gè)組件中引入Dialog,就最少需要額外維護(hù)一個(gè)visible變量。如果只是額外維護(hù)一個(gè)變量這也不是不能接受,可是當(dāng)同樣的Dialog組件,即需要在父組件控制它的展示與隱藏,又需要在子組件中控制。

          為了演示我們先實(shí)現(xiàn)一個(gè)MyDialog組件,代碼來自ElementPlus的Dialog示例

          html復(fù)制代碼<script setup lang="ts">
          import { computed } from 'vue';
          import { ElDialog } from 'element-plus';
          
          const props=defineProps<{
            visible: boolean;
            title?: string;
          }>();
          
          const emits=defineEmits<{
            (event: 'update:visible', visible: boolean): void;
            (event: 'close'): void;
          }>();
          
          const dialogVisible=computed<boolean>({
            get() {
              return props.visible;
            },
            set(visible) {
              emits('update:visible', visible);
              if (!visible) {
                emits('close');
              }
            },
          });
          </script>
          
          <template>
            <ElDialog v-model="dialogVisible" :title="title" width="30%">
              <span>This is a message</span>
              <template #footer>
                <span>
                  <el-button @click="dialogVisible=false">Cancel</el-button>
                  <el-button type="primary" @click="dialogVisible=false"> Confirm </el-button>
                </span>
              </template>
            </ElDialog>
          </template>
          

          演示場(chǎng)景

          就像下面這樣:

          示例代碼如下:

          html復(fù)制代碼<script setup lang="ts">
          import { ref } from 'vue';
          import { ElButton } from 'element-plus';
          
          import Comp from './components/Comp.vue';
          import MyDialog from './components/MyDialog.vue';
          
          const dialogVisible=ref<boolean>(false);
          const dialogTitle=ref<string>('');
          
          const handleOpenDialog=()=> {
            dialogVisible.value=true;
            dialogTitle.value='父組件彈窗';
          };
          
          const handleComp1Dialog=()=> {
            dialogVisible.value=true;
            dialogTitle.value='子組件1彈窗';
          };
          
          const handleComp2Dialog=()=> {
            dialogVisible.value=true;
            dialogTitle.value='子組件2彈窗';
          };
          </script>
          
          <template>
            <div>
              <ElButton @click="handleOpenDialog"> 打開彈窗 </ElButton>
              <Comp text="子組件1" @submit="handleComp1Dialog"></Comp>
              <Comp text="子組件2" @submit="handleComp2Dialog"></Comp>
              <MyDialog v-model:visible="dialogVisible" :title="dialogTitle"></MyDialog>
            </div>
          </template>
          

          這里的MyDialog會(huì)被父組件和兩個(gè)Comp組件都會(huì)觸發(fā),如果父組件并不關(guān)心子組件的onSubmit事件,那么這里的submit在父組件里唯一的作用就是處理Dialog的展示!!!這樣真的好嗎?不好!

          來分析一下,到底哪里不好!

          MyDialog本來是submit動(dòng)作的后續(xù)動(dòng)作,所以理論上應(yīng)該將MyDialog寫在Comp組件中。但是這里為了管理方便,將MyDialog掛在父組件上,子組件通過事件來控制MyDialog。

          再者,這里的handleComp1Dialog和handleComp2Dialog函數(shù)除了處理MyDialog外,對(duì)于父組件完全沒有意義卻寫在父組件里。

          如果這里的Dialog多的情況下,簡(jiǎn)直就是Dialog地獄啊!

          理想的父組件代碼應(yīng)該是這樣:

          html復(fù)制代碼<script setup lang="ts">
          import { ElButton } from 'element-plus';
          
          import Comp from './components/Comp.vue';
          import MyDialog from './components/MyDialog.vue';
          
          const handleOpenDialog=()=> {
            // 處理 MyDialog
          };
          </script>
          
          <template>
            <div>
              <ElButton @click="handleOpenDialog"> 打開彈窗 </ElButton>
              <Comp text="子組件1"></Comp>
              <Comp text="子組件2"></Comp>
            </div>
          </template>
          

          在函數(shù)中處理彈窗的相關(guān)邏輯才更合理。

          解決之道

          朕觀之,是書之文或不雅,致使人之心有所厭,何得無妙方可解決?

          依史記之辭曰:“天下苦Dialog久矣,苦楚深深,望有解脫之道?!庇谑牵T位賢哲紛紛舉起討伐Dialog之旌旗,終“命令式Dialog”逐漸突破困境之境地。

          沒錯(cuò)現(xiàn)在網(wǎng)上對(duì)于Dialog的困境,給出的解決方案基本上就“命令式Dialog”看起來比較優(yōu)雅!這里給出幾個(gè)網(wǎng)上現(xiàn)有的命令式Dialog實(shí)現(xiàn)。

          命令式一

          吐槽一下~,這種是能在函數(shù)中處理彈窗邏輯,但是缺點(diǎn)是MyDialog組件與showMyDialog是兩個(gè)文件,增加了維護(hù)的成本。

          命令式二

          基于第一種實(shí)現(xiàn)的問題,不就是想讓MyDialog.vue和.js文件合體嗎?于是諸位賢者想到了JSX。于是進(jìn)一步的實(shí)現(xiàn)是這樣:

          嗯,這下完美了!

          完美?還是要吐槽一下~

          • 如果我的系統(tǒng)中有很多彈窗,難道要給每個(gè)彈窗都寫成這樣嗎?
          • 這種兼容JSX的方式,需要引入支持JSX的依賴!
          • 如果工程中不想即用template又用JSX呢?
          • 如果已經(jīng)存在使用template的彈窗了,難道推翻重寫嗎?
          • ...

          思考

          首先承認(rèn)一點(diǎn)命令式的封裝的確可以解決問題,但是現(xiàn)在的封裝都存一定的槽點(diǎn)。

          如果有一種方式,即保持原來對(duì)話框的編寫方式不變,又不需要關(guān)心JSX和template的問題,還保存了命令式封裝的特點(diǎn)。這樣是不是就完美了?

          那真的可以同時(shí)做到這些嗎?

          如果存在一個(gè)這樣的Hook可以將狀態(tài)驅(qū)動(dòng)的Dialog,轉(zhuǎn)換為命令式的Dialog嗎,那不就行了?

          它來了:useCommandComponent

          父組件這樣寫:

          html復(fù)制代碼<script setup lang="ts">
          import { ElButton } from 'element-plus';
          
          import { useCommandComponent } from '../../hooks/useCommandComponent';
          
          import Comp from './components/Comp.vue';
          import MyDialog from './components/MyDialog.vue';
          
          const myDialog=useCommandComponent(MyDialog);
          </script>
          
          <template>
            <div>
              <ElButton @click="myDialog({ title: '父組件彈窗' })"> 打開彈窗 </ElButton>
              <Comp text="子組件1"></Comp>
              <Comp text="子組件2"></Comp>
            </div>
          </template>
          

          Comp組件這樣寫:

          html復(fù)制代碼<script setup lang="ts">
          import { ElButton } from 'element-plus';
          
          import { useCommandComponent } from '../../../hooks/useCommandComponent';
          
          import MyDialog from './MyDialog.vue';
          
          const myDialog=useCommandComponent(MyDialog);
          
          const props=defineProps<{
            text: string;
          }>();
          </script>
          
          <template>
            <div>
              <span>{{ props.text }}</span>
              <ElButton @click="myDialog({ title: props.text })">提交(需確認(rèn))</ElButton>
            </div>
          </template>
          

          對(duì)于MyDialog無需任何改變,保持原來的樣子就可以了!

          useCommandComponent真的做到了,即保持原來組件的編寫方式,又可以實(shí)現(xiàn)命令式調(diào)用!

          使用效果:

          是不是感受到了莫名的舒適?

          不過別急,要想體驗(yàn)這種極致的舒適,你的Dialog還需要遵循兩個(gè)約定!

          兩個(gè)約定

          如果想要極致舒適的使用useCommandComponent,那么彈窗組件的編寫就需要遵循一些約定(其實(shí)這些約定應(yīng)該是彈窗組件的最佳實(shí)踐)。

          約定如下:

          • 彈窗組件的props需要有一個(gè)名為visible的屬性,用于驅(qū)動(dòng)彈窗的打開和關(guān)閉。
          • 彈窗組件需要emit一個(gè)close事件,用于彈窗關(guān)閉時(shí)處理命令式彈窗。

          如果你的彈窗組件滿足上面兩個(gè)約定,那么就可以通過useCommandComponent極致舒適的使用了!!

          這兩項(xiàng)約定雖然不是強(qiáng)制的,但是這確實(shí)是最佳實(shí)踐!不信你去翻所有的UI框看看他們的實(shí)現(xiàn)。我一直認(rèn)為學(xué)習(xí)和生產(chǎn)中多學(xué)習(xí)優(yōu)秀框架的實(shí)現(xiàn)思路很重要!

          如果不遵循約定

          這時(shí)候有的同學(xué)可能會(huì)說:哎嘿,我就不遵循這兩項(xiàng)約定呢?我的彈窗就是要標(biāo)新立異的不用visible屬性來控制打開和關(guān)閉,我起名為dialogVisible呢?我的彈窗就是沒有close事件呢?我的事件是具有業(yè)務(wù)意義的submit、cancel呢?...

          得得得,如果真的沒有遵循上面的兩個(gè)約定,依然可以舒適的使用useCommandComponent,只不過在我看來沒那么極致舒適!雖然不是極致舒適,但也要比其他方案舒適的多!

          如果你的彈窗真的沒有遵循“兩個(gè)約定”,那么你可以試試這樣做:

          html復(fù)制代碼<script setup lang="ts">
          // ...
          const myDialog=useCommandComponent(MyDialog);
          
          const handleDialog=()=> {
            myDialog({ 
              title: '父組件彈窗', 
              dialogVisible: true, 
              onSubmit: ()=> myDialog.close(),
              onCancel: ()=> myDialog.close(),
            });
          };
          </script>
          
          <template>
            <div>
              <ElButton @click="handleDialog"> 打開彈窗 </ElButton>
              <!--...-->
            </div>
          </template>
          

          如上,只需要在調(diào)用myDialog函數(shù)時(shí)在props中將驅(qū)動(dòng)彈窗的狀態(tài)設(shè)置為true,在需要關(guān)閉彈窗的事件中調(diào)用myDialog.close()即可!

          這樣是不是看著雖然沒有上面的極致舒適,但是也還是挺舒適的?

          源碼與實(shí)現(xiàn)

          實(shí)現(xiàn)思路

          對(duì)于useCommandComponent的實(shí)現(xiàn)思路,依然是命令式封裝。相比于上面的那兩個(gè)實(shí)現(xiàn)方式,useCommandComponent是將組件作為參數(shù)傳入,這樣保持組件的編寫習(xí)慣不變。并且useCommandComponent遵循單一職責(zé)原則,只做好組件的掛載和卸載工作,提供足夠的兼容性。

          其實(shí)useCommandComponent有點(diǎn)像React中的高階組件的概念

          源碼

          源碼不長(zhǎng),也很好理解!在實(shí)現(xiàn)useCommandComponent的時(shí)候參考了ElementPlus的MessageBox。

          源碼如下:

          ts復(fù)制代碼import { AppContext, Component, ComponentPublicInstance, createVNode, getCurrentInstance, render, VNode } from 'vue';
          
          export interface Options {
            visible?: boolean;
            onClose?: ()=> void;
            appendTo?: HTMLElement | string;
            [key: string]: unknown;
          }
          
          export interface CommandComponent {
            (options: Options): VNode;
            close: ()=> void;
          }
          
          const getAppendToElement=(props: Options): HTMLElement=> {
            let appendTo: HTMLElement | null=document.body;
            if (props.appendTo) {
              if (typeof props.appendTo==='string') {
                appendTo=document.querySelector<HTMLElement>(props.appendTo);
              }
              if (props.appendTo instanceof HTMLElement) {
                appendTo=props.appendTo;
              }
              if (!(appendTo instanceof HTMLElement)) {
                appendTo=document.body;
              }
            }
            return appendTo;
          };
          
          const initInstance=<T extends Component>(
            Component: T,
            props: Options,
            container: HTMLElement,
            appContext: AppContext | null=null
          )=> {
            const vNode=createVNode(Component, props);
            vNode.appContext=appContext;
            render(vNode, container);
          
            getAppendToElement(props).appendChild(container);
            return vNode;
          };
          
          export const useCommandComponent=<T extends Component>(Component: T): CommandComponent=> {
            const appContext=getCurrentInstance()?.appContext;
          
            const container=document.createElement('div');
          
            const close=()=> {
              render(null, container);
              container.parentNode?.removeChild(container);
            };
          
            const CommandComponent=(options: Options): VNode=> {
              if (!Reflect.has(options, 'visible')) {
                options.visible=true;
              }
              if (typeof options.onClose !=='function') {
                options.onClose=close;
              } else {
                const originOnClose=options.onClose;
                options.onClose=()=> {
                  originOnClose();
                  close();
                };
              }
              const vNode=initInstance<T>(Component, options, container, appContext);
              const vm=vNode.component?.proxy as ComponentPublicInstance<Options>;
              for (const prop in options) {
                if (Reflect.has(options, prop) && !Reflect.has(vm.$props, prop)) {
                  vm[prop as keyof ComponentPublicInstance]=options[prop];
                }
              }
              return vNode;
            };
          
            CommandComponent.close=close;
          
            return CommandComponent;
          };
          
          export default useCommandComponent;
          

          除了命令式的封裝外,我加入了const appContext=getCurrentInstance()?.appContext;。這樣做的目的是,傳入的組件在這里其實(shí)已經(jīng)獨(dú)立于應(yīng)用的Vue上下文了。為了讓組件依然保持和調(diào)用方相同的Vue上下文,我這里加入了獲取上下文的操作!

          基于這個(gè)情況,在使用useCommandComponent時(shí)需要保證它在setup中被調(diào)用,而不是在某個(gè)點(diǎn)擊事件的處理函數(shù)中哦~

          最后

          如果你覺得useCommandComponent對(duì)你在開發(fā)中有所幫助,麻煩多點(diǎn)贊評(píng)論收藏

          如果useCommandComponent對(duì)你實(shí)現(xiàn)某些業(yè)務(wù)有所啟發(fā),麻煩多點(diǎn)贊評(píng)論收藏

          如果...,麻煩多點(diǎn)贊評(píng)論收藏

          如果大家有其他彈窗方案,歡迎留言交流哦!

          1. able控件:用于向用戶顯示信息。

          屬性:

          Text:向用戶展示的信息。

          1. 做一個(gè)小程序,目的是用戶永遠(yuǎn)點(diǎn)不到不喜歡按鈕。

          1、界面

          2、代碼

          namespace WindowsFormsApplication2

          {

          public partial class Form1 : Form

          {

          public Form1()

          {

          InitializeComponent();

          }

          //喜歡的單擊事件

          private void btnok_Click(object sender, EventArgs e)

          {

          MessageBox.Show("太好了,我也喜歡你!??!");

          }

          //不喜歡的鼠標(biāo)移動(dòng)事件

          private void btnNG_MouseMove(object sender, MouseEventArgs e)

          {

          Random size_X=new Random(); //定義一個(gè)隨機(jī)數(shù)對(duì)象

          int x=size_X.Next(0, this.ClientSize.Width - btnNG.Size.Width);

          int y=size_X.Next(0, this.ClientSize.Height - btnNG.Size.Height);

          Point point=new Point(x, y);

          btnNG.Location=point;

          }

          }

          }

          3、效果:

          永遠(yuǎn)點(diǎn)不到不喜歡按鈕。

          1. 窗體

          (1)屬性:

          FormBoarderStyle:窗體的邊緣樣式。

          Icon:窗體左上角的圖標(biāo)。

          MaximizeBox:最大化按鈕是否可用。

          Minimizebox:最小化按鈕是否可用。

          Opacity:透明度 0-1。

          ShowInTaskbar:是否在任務(wù)欄上顯示。

          StartPosition:?jiǎn)?dòng)程序時(shí),主窗體顯示的位置。

          Text:標(biāo)題欄中的文本。

          TopMost:保持在最上面,有可能擋住下面的窗體。

          WindowState:指示窗體處于是最大化還是最小化還是正常。

          ClientSize:指窗體工作區(qū)域的大小。

          1. 事件:

          Load(默認(rèn)):窗體在顯示之前最后一個(gè)被觸發(fā)的事件,所以我們一般在這里對(duì)窗體上的控件進(jìn)行賦值初始化。

          Activated:窗體獲得焦點(diǎn)時(shí)觸發(fā)。

          Deactivate:窗體失去焦點(diǎn)時(shí)觸發(fā)。

          注意:窗體的Enter和Leave事件被取消,請(qǐng)不要使用。

          FormClosing:窗體進(jìn)入關(guān)閉前觸發(fā)的事件。(即執(zhí)行完FormClosing事件里面的代碼后,窗體關(guān)閉)

          FormClosed:窗體關(guān)閉后觸發(fā)的事件。(即執(zhí)行完窗體關(guān)閉后,再執(zhí)行FormClosed事件里面的代碼)

          1. 方法:

          Close(); 關(guān)閉事件。

          Show(); 以非模態(tài)形式顯示。(顯示的窗體可以有多個(gè)相同的窗體,程序直接往下執(zhí)行)

          ShowDialog(); 以模態(tài)的形式顯示。(顯示的窗體具有唯一性,只有關(guān)閉當(dāng)前窗體,程序才往下執(zhí)行)

          this.Hide(); //本類隱藏,相當(dāng)于Visible賦值false。

          this.Show(); //本類顯示,相當(dāng)于Visible賦值true。

          btnButton.hide(); //名字叫btnButton的按鈕隱藏,相當(dāng)于Visible賦值false。

          btnButton.Show(); //名字叫btnButton的按鈕顯示,相當(dāng)于Visible賦值true。


          主站蜘蛛池模板: 国产精品香蕉一区二区三区| 成人精品视频一区二区三区| 成人区精品一区二区不卡 | 中文字幕一区二区三| 亚洲国产欧美日韩精品一区二区三区| 国产精品一区二区av不卡| 日韩美一区二区三区| 亚洲熟女www一区二区三区| 精品国产aⅴ无码一区二区| 人妻少妇精品视频一区二区三区| 国产一区二区在线观看app| 一级特黄性色生活片一区二区 | 大屁股熟女一区二区三区| 视频一区二区在线观看| 国产高清一区二区三区视频| 亚洲.国产.欧美一区二区三区| 亚洲日本一区二区| 一区二区三区视频在线| 日韩人妻精品一区二区三区视频| 日韩电影一区二区三区| 无码国产精成人午夜视频一区二区| 国产成人精品视频一区二区不卡 | 深夜福利一区二区| 日韩熟女精品一区二区三区| 精品一区二区三区中文| 精品福利一区3d动漫| 国产一区二区在线观看麻豆| 日本一区二区三区不卡视频中文字幕 | 香蕉久久一区二区不卡无毒影院| 亚洲国产精品一区二区久久hs| 国产在线精品一区二区不卡麻豆| 国产成人无码AV一区二区在线观看| 中文字幕精品一区二区精品| 亚洲AV乱码一区二区三区林ゆな| 亚洲av无码一区二区三区乱子伦 | 一区 二区 三区 中文字幕| 国产免费伦精品一区二区三区| 伦理一区二区三区| 精品一区二区三区波多野结衣| 亚洲一区二区三区丝袜| 国产激情一区二区三区四区 |