首页 > 解决方案 > 如何在 WFP C#.Net 中拆分相交标签?

问题描述

我创建了这个 WFP 应用程序,它在表单的某些位置生成标签,以显示基于其他表单设置的每周计划

界面

CustomLabel.Add(new Label()):
(CustomLabel[CustomLabel.Count - 1] as Label).Location = new System.Drawing.Point(117,Y(LISTPLANS[MainForm.indexplan].Subjects.ElementAt<Subject(i).PSchedule.StartTime));
(CustomLabel[CustomLabel.Count - 1] as Label).Size = new System.Drawing.Size(97,L(LISTPLANS[MainForm.indexplan].Subjects.ElementAt<Subject(i).PSchedule.StartTime,LISTPLANS[MainForm.indexplan].Subjects.ElementAt<Subject>(i).PSchedule.EndTime));
Controls.Add(CustomLabel[CustomLabel.Count - 1] as Control);

标签的大小和位置相对于开始日期时间和结束日期时间,当然还有日期:

public Int32 Y(DateTime StartTime)
{
    double onehour = 19.5;
    double minute = Math.Ceiling(StartTime.Minute / 15.0) / 4.0;
    switch (StartTime.Hour)
    {
        case 6:
            return (Int32)(94 + minute * onehour);
        case 7:
            return (Int32)(114 + minute * onehour);
        case 8:
            return (Int32)(135 + minute * onehour);
        case 9:
            return (Int32)(156 + minute * onehour);
        case 10:
            return (Int32)(177 + minute * onehour);
        case 11:
            return (Int32)(197 + minute * onehour);
        case 12:
            return (Int32)(219 + minute * onehour);
        case 13:
            return (Int32)(240 + minute * onehour);
        case 14:
            return (Int32)(260 + minute * onehour);
        case 15:
            return (Int32)(280 + minute * onehour);
        case 16:
            return (Int32)(302 + minute * onehour);
        case 17:
            return (Int32)(322 + minute * onehour);
        case 18:
            return (Int32)(344 + minute * onehour);
        case 19:
            return (Int32)(366 + minute * onehour);
        case 20:
            return (Int32)(388 + minute * onehour);
        case 21:
            return (Int32)(407 + minute * onehour);
        case 22:
            return (Int32)(428 + minute * onehour);
        case 23:
            return (Int32)(449 + minute * onehour);
        case 0:
            return (Int32)(470 + minute * onehour);
        default:
            return 0;
    }
}
public Int32 L(DateTime StartTime, DateTime EndTime)
{
    return (Int32)(Y(EndTime) - Y(StartTime));
}

我想通了,但问题仍然是如果用户输入的时间类似于先前保留的时间,程序将在旧的蚂蚁上创建一个标签,它将隐藏它,如果用户设置例如:Subject1:从 8: 00 -> 11:00 - 星期六 Subject2 : 从 10:00 -> 12:00 - 星期六 生成的两个标签将相互交叉。我想要一个分割这些相交标签的代码(默认宽度为 97),以便两者的宽度都为 48:

结果

标签: c#.netvisual-studio

解决方案


您需要首先将重叠的分组。这是一个例子来说明这个想法。

static IEnumerable<RectangleF> Layout(IEnumerable<(DateTime StartTime, DateTime EndTime)> source, SizeF area)
{
    static bool Overlaps(
        (DateTime StartTime, DateTime EndTime) a, 
        (DateTime StartTime, DateTime EndTime) b) =>
            a.StartTime <= b.StartTime && a.EndTime > b.StartTime ||
                a.StartTime <= b.EndTime && a.EndTime > b.EndTime;

    var set = new HashSet<(DateTime StartTime, DateTime EndTime)>();

    IEnumerable<RectangleF> results =
        from item in source
        let matches = source.Where(x => Overlaps(item, x) && set.Add(x)).ToList()
        from t in matches.Select((match, index) => (match, index))
        let y = t.match.StartTime.TimeOfDay.Ticks / TimeSpan.TicksPerDay * area.Height
        let height = (t.match.EndTime - t.match.StartTime).Ticks / TimeSpan.TicksPerDay * area.Height
        let x = t.index * 1f / matches.Count / area.Width
        let width = 1f / matches.Count * area.Width
        select new RectangleF(x, y, width, height);

    return results;
}

推荐阅读