为什么/如何使我能够在日历控件中选择多天
本文关键字:控件 选择 日历 何使我 为什么 | 更新日期: 2023-09-27 18:33:31
我一直在努力解决Calendar.SelectedDates是只读的事实。 我想要一种以编程方式选择日历中多个日期的方法。 我找到了以下代码片段,它完全符合我的需求,但我无法理解它为什么有效:
protected void Page_Load(object sender, EventArgs e)
{
SelectedDatesCollection dates = Calendar1.SelectedDates;
dates.Add(new DateTime(2012, 5, 1));
dates.Add(new DateTime(2012, 5, 5));
dates.Add(new DateTime(2012, 5, 9));
}
我所期望的(鉴于我对 C# 的了解有限(,完全相反:
protected void Page_Load(object sender, EventArgs e)
{
ArrayList datelist = new ArrayList();
datelist.Add(new DateTime(2012, 5, 1));
datelist.Add(new DateTime(2012, 5, 5));
datelist.Add(new DateTime(2012, 5, 9));
Calendar1.SelectedDates = new SelectedDatesCollection(datelist);
}
SelectedDates只读属性如何受到本地SelectedDatesCollection变量的影响? 为什么添加到该局部变量会影响 Calendar1.SelectedDates 属性?
(这只是一个拖放 ASP.Net 日历,没有更改/特殊属性(
作为属性的 SelectedDatesCollection 是只读的,但您仍然可以将其作为对象进行更改,就像在添加或删除项目中一样。
更改对象(即使用更改其数据调用其方法(与更改对象引用本身(作为类的成员等(之间存在差异。
通过做:
SelectedDatesCollection dates = Calendar1.SelectedDates;
您不是在复制集合,而只是保存它的引用,就像给它另一个名字一样。
最终,您还可以执行以下操作:
protected void Page_Load(object sender, EventArgs e)
{
Calendar1.SelectedDates.Add(new DateTime(2012, 5, 1));
Calendar1.SelectedDates.Add(new DateTime(2012, 5, 5));
Calendar1.SelectedDates.Add(new DateTime(2012, 5, 9));
}
只是有人会说另一种方式更具可读性。
dates
和Calendar1.SelectedDates
包含对完全相同对象的引用。在dates
上调用 Add
方法就像在 Calendar1.SelectedDates
上调用它一样,反之亦然。
正如您所说,您无法像尝试在第二段代码(无法编译(中那样重新分配Calendar1.SelectedDates
的原因是 SelectedDates 被标记为只读。
将成员标记为只读仅意味着它只会立即分配或在类/结构/等的构造函数中分配。
但是,这并不意味着您不能更改该对象中的数据。
从现在开始,它只是一些额外的信息
有一个类 ReadOnlyCollection,它不允许更改它的 ELEMENTS。
因此,例如,拥有只读 ReadOnlyCollection 意味着您无法更改成员,也无法更改元素。
例子:
public class Class1
{
public List<int> Numbers = new List<int> {1, 2, 3};
}
public class Class2
{
public readonly List<int> Numbers = new List<int> {1, 2, 3};
}
public class Class3
{
public ReadOnlyCollection<int> Numbers = new ReadOnlyCollection<int> {1, 2, 3};
}
public class Class3
{
public readonly ReadOnlyCollection<int> Numbers = new ReadOnlyCollection<int> {1, 2, 3};
}
差异:
var c1 = new Class1();
var c2 = new Class2();
var c3 = new Class3();
var c4 = new Class4();
c1.Numbers = new List<int> {4, 5, 6}; // Works
c1.Numbers.Clear(); // Works
c2.Numbers = new List<int> {4, 5, 6}; // Error
c2.Numbers = c2.Numbers; // Error - you just can't reassign it!
c2.Numbers.Clear(); // Works - you are just calling the Clear method of the existing list object.
c3.Numbers = new ReadOnlyCollection<int> {4, 5, 6}; // Works - the member is not readonly
// ReadOnlyCollection doesn't allow to change it's elements after initializing it.
// It doesn't even have these functions:
c3.Numbers.Clear(); // Error
c3.Numbers.Add(); // Error
c3.Numbers.Remove(2); // Error
c4.Numbers = new ReadOnlyCollection<int> {4, 5, 6}; // Error - the member is marked as readonly
// ReadOnlyCollection doesn't allow to change it's elements after initializing it.
// It doesn't even have these functions:
c4.Numbers.Clear(); // Error
c4.Numbers.Add(); // Error
c4.Numbers.Remove(2); // Error
请尝试以下操作 - 请记住,他们还需要能够取消选择日期:
protected void Page_Load(object sender, EventArgs e)
{
if (ViewState["StartDates"] == null)
{
startDates = new ArrayList();
}
else
{
startDates = ViewState["StartDates"] as ArrayList;
}
}
protected void StartSelection_Changed(Object sender, EventArgs e)
{
startCalendar.SelectedDate = new DateTime(startCalendar.SelectedDate.Year,
startCalendar.SelectedDate.Month, startCalendar.SelectedDate.Day, 0, 0, 0);
// c.f. http://www.mikepope.com/blog/AddComment.aspx?blogid=604
int index = -1;
index = startDates.IndexOf(startCalendar.SelectedDate);
if (index >= 0)
{
startDates.RemoveAt(index);
}
else
{
DateTime dateTime
= new DateTime(startCalendar.SelectedDate.Year,
startCalendar.SelectedDate.Month,
startCalendar.SelectedDate.Day, 0, 0, 0);
startDates.Add(dateTime);
}
ViewState["StartDates"] = startDates;
DisplaySelectedDates();
}
protected void DisplaySelectedDates()
{
startCalendar.SelectedDates.Clear();
for (int i = 0; i < startDates.Count; i++)
{
startCalendar.SelectedDates.Add((DateTime)startDates[i]);
}
}
您的问题有一个更简洁的答案:
SelectedDates只读属性如何受到本地SelectedDatesCollection变量的影响?为什么添加到该局部变量会影响 Calendar1.SelectedDates 属性?
SelectedDatesCollection
是引用类型;只读 SelectedDates
属性返回对该类型的对象的引用。 因此,局部变量也包含对该对象的引用。 由于该对象与日历控件引用的对象相同,因此对该对象的更改将反映在日历控件中。
这种情况产生的另一个问题:
这在设计类时会导致问题吗?
是的! 许多开发人员被引诱到一种虚假的安全感中,因为他们错误地假设,例如,通过只读属性公开列表将阻止使用者代码修改列表。 这当然不是真的:通过只读属性公开私有引用类型数据允许代码的用户更改对象。 例如:
class Parent
{
private readonly List<Child> _children = new List<Child>();
public List<Child> Children { get { return _children; } }
}
class SomeOtherClass
{
void EvilParentConsumer()
{
Parent a = GetSomeParent();
Parent b = GetSomeParent();
//Kidnap all of b's children and give them to a!!!
a.Children.AddRange(b.Children);
b.Children.Clear();
}
}
正如Yorye Nathan所指出的那样,您可以通过将私有列表公开为ReadOnlyCollection
来防止这种情况。 如果您的要求允许,另一种方法是将集合公开为IEnumerable<T>
,这不会公开向集合添加元素的方法。