2012-05-08 62 views
0

我摔跤的事實是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); 
} 

HOW是受當地SelectedDatesCollection變量影響的SelectedDates只讀屬性?爲什麼添加到本地變量會影響Calendar1.SelectedDates屬性?

(這僅僅是一拖N - 下降ASP.Net日曆,沒有改變/特殊屬性)

+0

所有這些答案都非常棒,幫助了我。希望我可以將所有標記爲答案。再次感謝。 – CptSupermrkt

回答

1

的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)); 
} 

這僅僅是一個會說的其他方式更具有可讀性。

datesCalendar1.SelectedDates包含對完全相同的對象的引用。 在dates上調用Add方法就像在Calendar1.SelectedDates上調用它,反之亦然。

當您嘗試在第二段代碼(不編譯)中嘗試執行Calendar1.SelectedDates時,原因是SelectedDates被標記爲只讀,如您所說。

將成員標記爲只讀意味着它只會立即或在類/結構體/等的構造函數中分配。

但是,它並不意味着您不能更改該對象內的數據。

從現在開始,它只是一些額外的信息

有一類ReadOnlyCollection,不允許改變它的元素。

因此,例如,只讀屬性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 
+0

太棒了!很多很好的信息在這裏學習。 – CptSupermrkt

1

請嘗試以下 - 記住他們需要能夠取消日期還有:

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]); 
     } 
    } 
+0

嘿,非常感謝。我在這條賽道上,只需要額外的推動,嘿。有一件事---這個方法(詳見該博客文章)使用了一個名爲startDates的全局變量(否則startDate = new ArrayList()失敗)。這有多安全?我學到的一般做法是避開全局變量。這會對網頁的其他訪問者產生什麼影響嗎? – CptSupermrkt

+0

我做了一些調整,並得到它的工作。唯一的辦法可能會變得混亂,如果你嘗試記錄時間以及...不要忘記標記爲A,如果它適合你:) – IrishChieftain

+0

@IrishChieftain這是一個很好的解決方案,但不是OP原來的問題,至於爲什麼一件事情可行,另一件事則不行。你的解決方案是「我怎樣才能以最好的方式工作?」 – SimpleVar

1

還有一個更簡潔回答你的問題:

HOW是受當地SelectedDatesCollection變量影響的SelectedDates只讀屬性?爲什麼添加到本地變量會影響Calendar1.SelectedDates屬性?

SelectedDatesCollection是參考類型;只讀SelectedDates屬性將引用返回到該類型的對象。局部變量因此也對該對象保持參考。由於該對象與CalendarControl引用的對象相同,因此對該對象的更改將反映在CalendarControl中。


是源自這種情況的另一個問題:

可以在設計一個類時,這個事業的問題?

是的!許多開發人員被錯誤的假設所誘惑,例如通過只讀屬性暴露列表將阻止消費者代碼修改列表。這當然是不正確的:通過只讀屬性公開私有引用類型數據允許您的代碼的用戶更改對象。例如:

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內森指出,可以通過暴露私有列表作爲ReadOnlyCollection防止這一點。如果您的要求允許,另一種方法是將該集合公開爲IEnumerable<T>,該公開方法不向組中添加元素。

相關問題