繁体   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