簡體   English   中英

C#-避免WinForm和UserControl之間的邏輯重復

[英]C# - Avoid duplicating logic between WinForm and UserControl

我發現一個我相信的問題就是我要尋找的東西,但是在回答中有些我沒有遵循。 因此,我想以不同的方式提出問題(感謝您的耐心配合)。 這是我指的鏈接:

如何避免在兩個相似的WinForms上重復邏輯?

好。 我創建了一個對話框。 我們有用於用戶輸入的控件,用於顯示其他對話框(以獲取其他輸入)的按鈕等。從審美的角度來看,我更喜歡對話框的控件垂直放置。 無論如何,我也在考慮創建此對話框的UserControl版本。 此UserControl具有所有相同的控件和相同的邏輯,但是控件的布局將完全不同(先水平,再垂直)。

因此,我不能只創建另一個(第三個)UserControl,並將其放在原始表單上,也要在要創建的UserControl上。 (然后,第3個UserControl將包含所有邏輯-從而在兩者之間共享)。 由於布局不同,我無法執行此操作。

我創建兩個控件(窗體,用戶控件)沒有問題,控件的布局不同,但是我不想將所有邏輯從一個邏輯“剪切並粘貼”到另一個邏輯。

對於MVP或MVC來說,似乎不是這種情況。 我的模型是對話框本身。 對話框是使用一些值初始化的,是的,但是一旦初始化,“模型”將成為進一步的用戶輸入(當他們按下“確定”按鈕時,我會抓住它)。

以下面的代碼為例(此對話框上我的一個按鈕的事件):

    private void EditQuery_Click(object sender, EventArgs e)
    {
        try
        {
            EditQueryParameters();
        }
        catch (System.Exception ex)
        {
            // TODO: Write ErrMsg to Log file.
            MessageBox.Show("Edit Query Parameters Error:\n\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

    private void EditQueryParameters()
    {
        if (m_ReportType.QueryScoreDetails && optPickDetail.Checked)
        {
            // This brings up a different type of dialog
            QueryDetails();
            return;
        }

        // DateRange, StartDate, and EndDate are all saved from the last time
        // I called this dialog
        DateType DtType = new DateType(m_ReportType.DBDateRangeField,
            m_DateRange, m_StartDate, m_EndDate);
        // StartTime, EndTime too!
        TimeType TmType = new TimeType(m_ReportType.DBTimeRangeField,
            m_StartTime, m_EndTime);

        List<AdvancedFilter> Filters = null;
        if (lstAdvancedQuery.Items.Count > 0)
        {
            Filters = new List<AdvancedFilter>();
        }
        for (int i = 0; i < lstAdvancedQuery.Items.Count; ++i)
        {
            Filters.Add((AdvancedFilter)lstAdvancedQuery.Items[i]);
        }

        // QueryType is also saved from the last time I called QueryBuilder
        QueryBuilder QryBuilder = new QueryBuilder(m_ReportType.DBCatalog, m_ReportType.DBTable,
            m_QueryType, ref DtType, ref TmType, ref Filters);

        // I am using Visual WebGUI, I have to do it this way
        QryBuilder.Closed += new EventHandler(QryBuilder_Closed);
        QryBuilder.ShowDialog();
    }

我的意思是,我想我可以有一些“邏輯”類,它公開了以下內容:

    public void EditQueryParameters(ref ReportType RptType, bool PickDetail,
         string DateRange, DateTime StartDate, DateTime EndDate,
         DateTime StartTime, DateTime EndTime, string QueryType)
    {
        if (ReportType.QueryScoreDetails && PickDetail)
        {
            // This brings up a different type of dialog
            QueryDetails();
            return;
        }


        DateType DtType = new DateType(ReportType.DBDateRangeField,
            DateRange, StartDate, EndDate);
        TimeType TmType = new TimeType(ReportType.DBTimeRangeField,
            StartTime, EndTime);

        // Yikes, more stuff to add to the signature of my method
        // Will have to pull this outside the method and pass in Filters
        List<AdvancedFilter> Filters = null;
        if (lstAdvancedQuery.Items.Count > 0)
        {
            Filters = new List<AdvancedFilter>();
        }
        for (int i = 0; i < lstAdvancedQuery.Items.Count; ++i)
        {
            Filters.Add((AdvancedFilter)lstAdvancedQuery.Items[i]);
        }

        // QueryType is also saved from the last time I called QueryBuilder
        QueryBuilder QryBuilder = new QueryBuilder(ReportType.DBCatalog, ReportType.DBTable,
            QueryType, ref DtType, ref TmType, ref Filters);

        // I am using Visual WebGUI, I have to do it this way
        QryBuilder.Closed += new EventHandler(QryBuilder_Closed);
        QryBuilder.ShowDialog();
    }

有很多設置可以使用此方法。 我不知道,也許我在尋找更多..“光滑”?

最重要的是,查看我的部分(不是全部)初始化代碼(這是從構造函數或form_Load調用的;將其添加到邏輯類似乎並不值得,因此仍然可以在它們之間“剪切並粘貼”所有代碼)他們倆):

    private void InitializeUserDefinedTitle()
    {
        txtUserTitle.Text = m_UserTitle;
    }

    private void InitializePrintSelectionCriteria()
    {
        // Print Selection Criteria
        chkSelectionCriteria.Checked = m_printSelectionCriteria;
    }

    private void InitializeTrendBy()
    {
        cmbTrend.Items.AddRange(Enum.GetNames(typeof(TrendBy)));
        cmbTrend.SelectedIndex = (int)m_TrendBy;
        cmbTrend.Visible = m_ReportType.TrendVisible;
        lblTrend.Visible = m_ReportType.TrendVisible;
    }

總之,原始WinForm是一個初始化了數據的對話框(構造函數),向用戶顯示以供輸入,當他們確定該對話框時,便檢索到該數據(並且該數據存儲在該對話框的外部,在成員變量中,用於下次他們調用對話框時-這是因為我們想顯示他們上一次選擇/輸入的內容。

我剛才描述的那種對話框也將是一個用戶控件,並且邏輯應該在兩者之間共享。

謝謝。

您可以制作兩個控件A和B,每個控件包含相同的按鈕和/或其他輸入控件,排列方式不同。 控件A和B將具有相同的屬性和事件。 該窗體(或第三個控件)將包含事件處理程序,這些事件處理程序允許將邏輯僅包含在一個位置。

您可以使用visible屬性或通過在container.controls屬性中添加一個控件來顯示控件A或B,其中容器是包含窗體或控件。

而且,例如,與其在控件A和B中的button1的處理程序沒有處理按鈕按下的完整邏輯,不如在控件A和B中的button1的處理程序將引發一個事件,該事件將由控件的容器處理A或B。

與其封裝邏輯,不如封裝布局。 使用用戶控件的屬性來指定所需的布局。 然后,無論它在哪里(獨立表單,同一表單上的三個實例之一,無論如何),都可以訪問它並以相同的方式指定布局。

至於如何封裝布局,有很多可能性。 您可以以編程方式進行操作,即編寫每個版本的布局代碼。 (如果您使用某種布局容器(例如WPF中的面板),則編程版本會更干凈。)您可以在設計器中繪制布局,然后復制生成的代碼。 布局邏輯的不同版本可以填充到私有方法中,或封裝到對象中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM