C# 避免在WinForm和UserControl之间重复逻辑

C# 避免在WinForm和UserControl之间重复逻辑,c#,winforms,design-patterns,C#,Winforms,Design Patterns,我发现了一个我相信是我一直在寻找的问题,但在答案中有一些我没有遵循的东西。因此,我想用另一种方式问这个问题,谢谢你的耐心。以下是我所指的链接: 嗯。我创建了一个对话框。我们有用于用户输入的控件,用于显示其他对话框以获得其他输入的按钮,等等。从美学角度来说,我更喜欢控件垂直布置的对话框。无论如何,我也在考虑为这个对话框创建一个用户控件版本。这个用户控件将具有所有相同的控件和所有相同的逻辑,但是这些控件的布局将完全不同,先是水平的,然后是垂直的 所以,我不能仅仅创建另一个我放在原始表单上的第三个Us

我发现了一个我相信是我一直在寻找的问题,但在答案中有一些我没有遵循的东西。因此,我想用另一种方式问这个问题,谢谢你的耐心。以下是我所指的链接:

嗯。我创建了一个对话框。我们有用于用户输入的控件,用于显示其他对话框以获得其他输入的按钮,等等。从美学角度来说,我更喜欢控件垂直布置的对话框。无论如何,我也在考虑为这个对话框创建一个用户控件版本。这个用户控件将具有所有相同的控件和所有相同的逻辑,但是这些控件的布局将完全不同,先是水平的,然后是垂直的

所以,我不能仅仅创建另一个我放在原始表单上的第三个UserControl,以及我想要创建的UserControl。这个第三个用户控件将包含所有逻辑——因此,在两者之间共享。我不能这样做,因为不同的布局

我在创建两个表单UserControl时没有问题,控件的布局不同,但我不想将所有逻辑从一个表单“剪切并粘贴”到另一个表单

这似乎不是MVP或MVC的情况。我的模型是对话框本身。对话框初始化为一些值,是的,但一旦初始化,模型就变成了进一步的用户输入,当他们按下OK按钮时,我会抓取这些输入

例如,此代码是此对话框上我的一个按钮的事件:

    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();
    }
总而言之,原始WinForm是一个对话框,它是使用数据构造函数初始化的,当用户确定该对话框时,会向用户显示以供输入,当用户下次调用该对话框时,将检索数据,并将数据存储在该对话框外的成员变量中-这是因为我们希望显示用户上次选择/输入的内容

我刚才描述的那种类型的对话框也是一个用户控件,逻辑应该在两者之间共享


谢谢。

我将封装布局,而不是封装逻辑。使用用户控件的属性指定所需的布局。然后,无论它是独立表单,同一表单上的三个实例中的一个,无论您如何访问它并以相同的方式指定布局


至于如何封装布局,有很多可能性。您可以通过编程来完成,即编写每个版本的布局代码。如果使用某种布局容器,如WPF中的面板,则ProgrammaMatic版本会更干净。您可以在设计器中绘制布局,并复制生成的代码。布局逻辑的不同版本可以填充到私有方法中,也可以封装到对象中。

您可以创建两个控件A和B,每个控件包含相同的按钮和/或其他不同排列的输入控件。控件A和B将具有相同的属性和事件。表单或第三个控件将包含事件处理程序,这些事件处理程序只允许将逻辑包含在一个位置

您可以使用visible属性显示控件A或B,也可以将控件A或B添加到container.controls属性中,容器是包含窗体或控件的


例如,控件a和B中的button1处理程序不处理按钮按下的完整逻辑,而控件a和B中的button1处理程序只会引发一个事件,该事件将由控件a或B的容器处理。

如果您只是想调整布局,您查看过FlowLayoutPanel控件吗?它允许快速和简单的VRT进行水平和向后定位……我是一个C++程序员,在过去的一个月左右一直在学习C,所以我从未听说过。谢谢。我如何给你一些分数或什么?有趣的想法,我今天会尝试一下。这也是一个好主意。我没有使用WPF,我喜欢复制genrated代码的想法,尽管没有在上面销售。你给了我一些今天要处理的想法。
    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();
    }
    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;
    }