在 Xamarin 表单应用程序中创建 outlook 样式事件
Creating outlook style occurrences in Xamarin forms application
我有一组复选框代表一周中的几天我还有一个开始日期和结束日期。我不想要的是 outlook 如何处理其日历中的日子,但我有点不知所措如何计算它。我打算使用这个库,但它与 Xamarin 表单不兼容。 https://github.com/SergeyBarskiy/RecurrenceCalculator。当我说不起作用时它没有在 quite 中更新一段时间所以与 XF 不兼容。
星期列表中的日子将以逗号分隔,即 Mon、Tue、Wed,但可能没有 Thur、Fri、Sunday
我需要一些方法来计算最坏情况下的日期,我可以在基于服务器的 api 上完成。但我宁愿在用户设备上进行。
if (picksessionType.SelectedItem.ToString() == Enums.RepeatOccurance.Daily.ToString())
{
foreach (var item in daysOfWeekList)
{
Session session = new Session();
session.Name = "\r\n" + txtName.Text + "\r\n" + item.ToString() + "\r\n";
session.StartDate = txtDateStartEntry.SelectedDate; // I obv need to shift this date to each date in days of week list
session.EndDate = txtDateEndEntry.SelectedDate;
session.IsActive = true;
session.IsDeleted = false;
await api.AddToSession(session);
}
await DisplayAlert(Constants.AppName, "Sessions Created For "+daysOfWeekList.ToString(), "OK");
}
目前在ui我正在做以下事情
<Frame x:Name="daySelector" IsVisible="false">
<StackLayout Orientation="Horizontal">
<syncfusion:SfCheckBox x:Name="daySun" Text="Sun" StateChanged="SfCheckBox_StateChanged" Visual="Material"></syncfusion:SfCheckBox>
<syncfusion:SfCheckBox x:Name="dayMon" Text="Mon" StateChanged="SfCheckBox_StateChanged" Visual="Material"></syncfusion:SfCheckBox>
<syncfusion:SfCheckBox x:Name="dayTue" Text="Tue" StateChanged="SfCheckBox_StateChanged" Visual="Material"></syncfusion:SfCheckBox>
<syncfusion:SfCheckBox x:Name="dayWed" Text="Wed" StateChanged="SfCheckBox_StateChanged" Visual="Material"></syncfusion:SfCheckBox>
<syncfusion:SfCheckBox x:Name="dayThur" Text="Thur" StateChanged="SfCheckBox_StateChanged" Visual="Material"></syncfusion:SfCheckBox>
<syncfusion:SfCheckBox x:Name="dayFri" Text="Fri" StateChanged="SfCheckBox_StateChanged" Visual="Material"></syncfusion:SfCheckBox>
<syncfusion:SfCheckBox x:Name="daySat" Text="Sat" StateChanged="SfCheckBox_StateChanged" Visual="Material"></syncfusion:SfCheckBox>
</StackLayout>
</Frame>
如果有人有新的更好的整理方法,此功能还可以进行一些令人震惊的整理工作。
private void SfCheckBox_StateChanged(object sender, StateChangedEventArgs e)
{
var selectedDay = sender as SfCheckBox;
daysOfWeekList.Add(selectedDay.Text);
List<string> distinct = daysOfWeekList.Distinct().ToList();
if (daySun.IsChecked == false)
distinct.Remove(daySun.Text);
if (dayMon.IsChecked == false)
distinct.Remove(dayMon.Text);
if (dayTue.IsChecked == false)
distinct.Remove(dayTue.Text);
if (dayWed.IsChecked == false)
distinct.Remove(dayWed.Text);
if (dayThur.IsChecked == false)
distinct.Remove(dayThur.Text);
if (dayFri.IsChecked == false)
distinct.Remove(dayFri.Text);
if (daySat.IsChecked == false)
distinct.Remove(daySat.Text);
daysOfWeekList = distinct;
}
Ui 例子
所以在 UI 示例中,您会看到我选择了两个日期,然后我选择了 Daily
选择周一、周二、周三、周四直到结束日期,它应该在上面的 for 循环中为选中的每一天创建会话。
提前致谢
编辑 2
我已经尝试了上面的代码,但是因为我在这些条件之间选择了星期五,它说他们应该创建 9 个会话,但我认为应该只创建 8 个,因为第 27 个是截止点,但系统仍在为28号
这是我的示例的 .netFiddle
https://dotnetfiddle.net/N6nkgP
单元测试
星期几枚举值
https://docs.microsoft.com/en-us/dotnet/api/system.dayofweek?view=net-6.0
using System;
using NUnit.Framework;
using System.Collections.Generic;
namespace TestApp {
public class Program
{
public static void Main()
{
var x = new NUnitLite.AutoRun().Execute(new string[]{"--test:TestApp.CalculateOccuranceTests", "--noc"});
Console.WriteLine("");
Console.WriteLine("----------------------------------------------");
Console.WriteLine(x==0?"All Test Passed... :¬)": string.Format("{0} tests failed... :¬(", x));
Console.WriteLine("----------------------------------------------");
}
}
[TestFixture]
public class CalculateOccuranceTests
{
[TestCase(8,"2022-01-10" ,"2022-01-27",2,3,5 )]
public void OccuranceTest(int expected,DateTime startDate, DateTime endDate, params int[] numbers)
{
//Setup
List<int> daysofWeek = new List<int>();
foreach (var item in numbers)
{
daysofWeek.Add(item);
Console.WriteLine("Date Selected " + item.ToString());
}
//act
var act = CalculateDaysToSessions( startDate, endDate, daysofWeek);
//Assert
Assert.AreEqual(expected,act.Count);
}
public List<DateTime> CalculateDaysToSessions(DateTime startDate, DateTime enddate, List<int> daysOfWeek)
{
List<DateTime> dates = new List<DateTime>();
DateTime date = new DateTime();
date = startDate;
while (date <= enddate)
{
if (daysOfWeek.Contains((int)date.DayOfWeek))
{
dates.Add(date);
Console.WriteLine("Date Session " + date.ToString("dd/MM/yyyy"));
}
date = date.AddDays(1);
}
return dates;
}
}
}
以上输出
Date Selected 2 =Tuesday
Date Selected 3 =Wednesday
Date Selected 5 =Friday
Date Session 11/01/2022
Date Session 12/01/2022
Date Session 14/01/2022
Date Session 18/01/2022
Date Session 19/01/2022
Date Session 21/01/2022
Date Session 25/01/2022
Date Session 26/01/2022
Date Session 28/01/2022
当它不应该创建第 28 个时
我所要做的就是在它现在按预期工作的时候这样做。
if (date > enddate) date = date.AddDays(-1);
编辑 3
Jason 是正确的 date.AddDays 必须在循环的底部不需要 if 语句
计算这个的算法应该很简单。只需在开始日期和结束日期之间循环,并检查每次迭代以查看它是否是用户选择的日期之一
// this is pseudo-c# and may need to be cleaned up a bit
List<DaysOfWeek> days = // initialize this based on the user selections
List<DateTime> dates = new List<DateTime>();
var date = StartDate;
while (date <= EndDate)
{
if (days.Includes(date.DayOfWeek))
{
dates.Add(date);
}
date = date.AddDays(1);
}
我有一组复选框代表一周中的几天我还有一个开始日期和结束日期。我不想要的是 outlook 如何处理其日历中的日子,但我有点不知所措如何计算它。我打算使用这个库,但它与 Xamarin 表单不兼容。 https://github.com/SergeyBarskiy/RecurrenceCalculator。当我说不起作用时它没有在 quite 中更新一段时间所以与 XF 不兼容。
星期列表中的日子将以逗号分隔,即 Mon、Tue、Wed,但可能没有 Thur、Fri、Sunday
我需要一些方法来计算最坏情况下的日期,我可以在基于服务器的 api 上完成。但我宁愿在用户设备上进行。
if (picksessionType.SelectedItem.ToString() == Enums.RepeatOccurance.Daily.ToString())
{
foreach (var item in daysOfWeekList)
{
Session session = new Session();
session.Name = "\r\n" + txtName.Text + "\r\n" + item.ToString() + "\r\n";
session.StartDate = txtDateStartEntry.SelectedDate; // I obv need to shift this date to each date in days of week list
session.EndDate = txtDateEndEntry.SelectedDate;
session.IsActive = true;
session.IsDeleted = false;
await api.AddToSession(session);
}
await DisplayAlert(Constants.AppName, "Sessions Created For "+daysOfWeekList.ToString(), "OK");
}
目前在ui我正在做以下事情
<Frame x:Name="daySelector" IsVisible="false">
<StackLayout Orientation="Horizontal">
<syncfusion:SfCheckBox x:Name="daySun" Text="Sun" StateChanged="SfCheckBox_StateChanged" Visual="Material"></syncfusion:SfCheckBox>
<syncfusion:SfCheckBox x:Name="dayMon" Text="Mon" StateChanged="SfCheckBox_StateChanged" Visual="Material"></syncfusion:SfCheckBox>
<syncfusion:SfCheckBox x:Name="dayTue" Text="Tue" StateChanged="SfCheckBox_StateChanged" Visual="Material"></syncfusion:SfCheckBox>
<syncfusion:SfCheckBox x:Name="dayWed" Text="Wed" StateChanged="SfCheckBox_StateChanged" Visual="Material"></syncfusion:SfCheckBox>
<syncfusion:SfCheckBox x:Name="dayThur" Text="Thur" StateChanged="SfCheckBox_StateChanged" Visual="Material"></syncfusion:SfCheckBox>
<syncfusion:SfCheckBox x:Name="dayFri" Text="Fri" StateChanged="SfCheckBox_StateChanged" Visual="Material"></syncfusion:SfCheckBox>
<syncfusion:SfCheckBox x:Name="daySat" Text="Sat" StateChanged="SfCheckBox_StateChanged" Visual="Material"></syncfusion:SfCheckBox>
</StackLayout>
</Frame>
如果有人有新的更好的整理方法,此功能还可以进行一些令人震惊的整理工作。
private void SfCheckBox_StateChanged(object sender, StateChangedEventArgs e)
{
var selectedDay = sender as SfCheckBox;
daysOfWeekList.Add(selectedDay.Text);
List<string> distinct = daysOfWeekList.Distinct().ToList();
if (daySun.IsChecked == false)
distinct.Remove(daySun.Text);
if (dayMon.IsChecked == false)
distinct.Remove(dayMon.Text);
if (dayTue.IsChecked == false)
distinct.Remove(dayTue.Text);
if (dayWed.IsChecked == false)
distinct.Remove(dayWed.Text);
if (dayThur.IsChecked == false)
distinct.Remove(dayThur.Text);
if (dayFri.IsChecked == false)
distinct.Remove(dayFri.Text);
if (daySat.IsChecked == false)
distinct.Remove(daySat.Text);
daysOfWeekList = distinct;
}
Ui 例子
所以在 UI 示例中,您会看到我选择了两个日期,然后我选择了 Daily 选择周一、周二、周三、周四直到结束日期,它应该在上面的 for 循环中为选中的每一天创建会话。
提前致谢
编辑 2
我已经尝试了上面的代码,但是因为我在这些条件之间选择了星期五,它说他们应该创建 9 个会话,但我认为应该只创建 8 个,因为第 27 个是截止点,但系统仍在为28号
这是我的示例的 .netFiddle
https://dotnetfiddle.net/N6nkgP
单元测试
星期几枚举值 https://docs.microsoft.com/en-us/dotnet/api/system.dayofweek?view=net-6.0
using System;
using NUnit.Framework;
using System.Collections.Generic;
namespace TestApp {
public class Program
{
public static void Main()
{
var x = new NUnitLite.AutoRun().Execute(new string[]{"--test:TestApp.CalculateOccuranceTests", "--noc"});
Console.WriteLine("");
Console.WriteLine("----------------------------------------------");
Console.WriteLine(x==0?"All Test Passed... :¬)": string.Format("{0} tests failed... :¬(", x));
Console.WriteLine("----------------------------------------------");
}
}
[TestFixture]
public class CalculateOccuranceTests
{
[TestCase(8,"2022-01-10" ,"2022-01-27",2,3,5 )]
public void OccuranceTest(int expected,DateTime startDate, DateTime endDate, params int[] numbers)
{
//Setup
List<int> daysofWeek = new List<int>();
foreach (var item in numbers)
{
daysofWeek.Add(item);
Console.WriteLine("Date Selected " + item.ToString());
}
//act
var act = CalculateDaysToSessions( startDate, endDate, daysofWeek);
//Assert
Assert.AreEqual(expected,act.Count);
}
public List<DateTime> CalculateDaysToSessions(DateTime startDate, DateTime enddate, List<int> daysOfWeek)
{
List<DateTime> dates = new List<DateTime>();
DateTime date = new DateTime();
date = startDate;
while (date <= enddate)
{
if (daysOfWeek.Contains((int)date.DayOfWeek))
{
dates.Add(date);
Console.WriteLine("Date Session " + date.ToString("dd/MM/yyyy"));
}
date = date.AddDays(1);
}
return dates;
}
}
}
以上输出
Date Selected 2 =Tuesday
Date Selected 3 =Wednesday
Date Selected 5 =Friday
Date Session 11/01/2022
Date Session 12/01/2022
Date Session 14/01/2022
Date Session 18/01/2022
Date Session 19/01/2022
Date Session 21/01/2022
Date Session 25/01/2022
Date Session 26/01/2022
Date Session 28/01/2022
当它不应该创建第 28 个时
我所要做的就是在它现在按预期工作的时候这样做。
if (date > enddate) date = date.AddDays(-1);
编辑 3 Jason 是正确的 date.AddDays 必须在循环的底部不需要 if 语句
计算这个的算法应该很简单。只需在开始日期和结束日期之间循环,并检查每次迭代以查看它是否是用户选择的日期之一
// this is pseudo-c# and may need to be cleaned up a bit
List<DaysOfWeek> days = // initialize this based on the user selections
List<DateTime> dates = new List<DateTime>();
var date = StartDate;
while (date <= EndDate)
{
if (days.Includes(date.DayOfWeek))
{
dates.Add(date);
}
date = date.AddDays(1);
}