ค่าเริ่มต้นของแอตทริบิวต์สามารถรับประกันความถูกต้องของแอตทริบิวต์ได้
ความถูกต้องในการตรวจสอบแอตทริบิวต์สามารถใช้เพื่อตรวจสอบแอตทริบิวต์อินพุตและการโทรกลับที่จำเป็นของแอตทริบิวต์ กล่าวคือ ต้องทำการแจ้งเตือนไม่ว่าแอตทริบิวต์จะมีการเปลี่ยนแปลงหรือไม่ก็ตาม
การแจ้งเตือนการเปลี่ยนแปลงคุณลักษณะ เมื่อคุณลักษณะเปลี่ยนแปลง โปรแกรมจะได้รับแจ้งให้ดำเนินการชุดของกระบวนการ
ไม่มีอะไรผิดปกติกับ WPF ที่นี่ มาดูกันว่าคุณสมบัติการพึ่งพาช่วยแก้ปัญหาข้างต้นได้อย่างไร
สรุปเนื้อหากำหนดค่าแอตทริบิวต์การพึ่งพาแอตทริบิวต์แรกและที่ง่ายที่สุด การอ้างอิงค่าแอตทริบิวต์การดำเนินการพื้นฐาน ข้อมูลเมตาของแอตทริบิวต์ wrapper คุณลักษณะ (PropertyMetadata)
ลักษณะการทำงานพื้นฐานของข้อมูลเมตาของแอตทริบิวต์
แม้ว่าคำดั้งเดิมของ MSDN จะตรงไปตรงมา แต่ก็ไม่มีข้อสงสัยเกี่ยวกับความถูกต้องของคำเหล่านั้น เมื่อคุณเข้าใจแล้ว คุณจะมีประสบการณ์ที่แตกต่างออกไปเมื่อพิจารณาดู
1. กำหนดแอตทริบิวต์การพึ่งพาแรกและง่ายที่สุด
คำดั้งเดิมของ MSDN: Windows Presentation Foundation (WPF) มอบชุดบริการที่สามารถใช้เพื่อขยายฟังก์ชันการทำงานของคุณสมบัติ Common Language Runtime (CLR) บริการเหล่านี้มักเรียกรวมกันว่าระบบทรัพย์สิน WPF คุณสมบัติที่สนับสนุนโดยระบบคุณสมบัติ WPF เรียกว่าคุณสมบัติการพึ่งพา
มากำหนดแอตทริบิวต์การพึ่งพาอายุดังต่อไปนี้:
DPCustomPeople คลาสสาธารณะ
-
สาธารณะ DependencyProperty แบบอ่านอย่างเดียวแบบคงที่ AgeProperty =
DependencyProperty.Register("อายุ", typeof(int), typeof(DPCustomPeople));
โมฆะสาธารณะ DisplayAgeProperty()
-
Console.WriteLine("DPName:" + DPCustomPeople.AgeProperty.Name);
Console.WriteLine ("DPPropertyType:" + DPCustomPeople.AgeProperty.PropertyType);
Console.WriteLine ("DPOWNerType:" + DPCustomPeople.AgeProperty.OwnerType);
-
-
แล้วเรียกผลลัพธ์ออกมา
โปรแกรมชั้นเรียน
-
โมฆะคงที่หลัก (สตริง [] args)
-
คน DPCustomPeople = DPCustomPeople ใหม่ ();
คน DisplayAgeProperty ();
-
-
คุณอาจไม่คุ้นเคยกับคลาส DependencyProperty คลาส DependencyProperty มีคุณสมบัติพื้นฐานบางอย่างของคุณสมบัติการพึ่งพา
วิธีการลงทะเบียนคุณสมบัติการพึ่งพาคือการเรียกเมธอดการลงทะเบียนแบบคงที่ของ DependencyProperty ซึ่งมีวิธีการโอเวอร์โหลดหลายวิธี แต่จำเป็นต้องมีสามขั้นตอนต่อไปนี้ เมื่อการลงทะเบียนเสร็จสมบูรณ์ จะเป็นคุณสมบัติแบบคงที่
ระบุชื่อที่จดทะเบียน (ชื่อ) “อายุ”
ลงทะเบียนประเภทคุณสมบัติ (PropertyType) typeof (int)
ลงทะเบียนประเภทเจ้าของของแอตทริบิวต์การพึ่งพา (OwnerType) typeof (DPCustomPeople)
หมายเหตุ: ชื่อแอตทริบิวต์ ประเภทแอตทริบิวต์ และประเภทเจ้าของแอตทริบิวต์ไม่สามารถเปลี่ยนแปลงได้เมื่อลงทะเบียนแล้ว
ต่อไปนี้คือผลลัพธ์ที่ได้
2. การดำเนินการพื้นฐานของค่าแอตทริบิวต์ที่ขึ้นต่อกัน (การได้มาและการกำหนดมูลค่า)
หลังจากกำหนดคุณสมบัติการพึ่งพาอายุแล้ว เราควรจะสามารถดำเนินการรับและมอบหมายมูลค่าในคุณสมบัตินั้นได้ DependencyProperty เองไม่ได้จัดเตรียมการดำเนินการเหล่านี้ แต่ได้รับการจัดการโดย DependencyObject
DependencyObject แสดงถึงอ็อบเจ็กต์ที่มีส่วนร่วมในระบบคุณสมบัติการพึ่งพา
ดังนั้นจึงจำเป็นที่คลาสที่กำหนดสืบทอดมาจาก DependencyObject จากนั้นจึงเขียน DPCustomPeople ใหม่
คลาสสาธารณะ DPCustomPeople:System.Windows.DependencyObject
-
-
การดำเนินการกำหนดค่าพื้นฐานวิธี GetValue และ SetValue
โมฆะสาธารณะ DPPropertyBasicOperator ()
-
Console.WriteLine ("อายุ:" + this.GetValue (DPCustomPeople.AgeProperty));
นี้. SetValue (DPCustomPeople.AgeProperty, 24);
Console.WriteLine("ChangedAge:" + this.GetValue(DPCustomPeople.AgeProperty));
-
ผลลัพธ์เอาท์พุต
3. wrapper แอตทริบิวต์ใช้วิธีการ GetValue และ SetValue เพื่อดำเนินการกับค่า เพื่อให้เราสามารถล้อมและกำหนดแอตทริบิวต์ Age ได้
อายุ int สาธารณะ
-
รับ { ผลตอบแทน (int) GetValue (AgeProperty); }
ตั้งค่า { SetValue (AgeProperty, มูลค่า }
-
หมายเหตุ: แบบแผนการตั้งชื่อสำหรับบรรจุภัณฑ์ของคุณสมบัติที่ขึ้นต่อกันคือการลบคุณสมบัติต่อไปนี้
โมฆะสาธารณะ DPPropertyBasicOperatorUsingProperty ()
-
Console.WriteLine("อายุ:" + this.Age);
นี่อายุ=24;
Console.WriteLine("ChangedAge:" + this.Age);
-
โค้ดด้านบนดูกระชับกว่านี้หรือไม่
4. ข้อมูลเมตาของคุณสมบัติ (PropertyMetadata)
ต้นฉบับของ MSDN: ระบบคุณสมบัติ Windows Presentation Foundation (WPF) รวมถึงระบบการรายงานข้อมูลเมตาที่ไม่จำกัดเฉพาะสิ่งที่สามารถรายงานเกี่ยวกับคุณสมบัติผ่านการสะท้อนหรือคุณสมบัติรันไทม์ภาษาทั่วไป (CLR) ปกติ
เมื่อพูดถึงข้อมูลเมตาของแอตทริบิวต์ สิ่งแรกที่นึกถึงคือแอตทริบิวต์ของ .net
บุคคลในชั้นเรียนสาธารณะ
-
[DefaultValue(200),หมวดหมู่("เค้าโครง")]
ความกว้าง int สาธารณะ { รับ;
-
แอตทริบิวต์จำเป็นต้องใช้พลังของ Visual Studio เพื่อให้การสนับสนุน IDE ที่เป็นมิตรสำหรับแอตทริบิวต์ หรืออาศัยการสะท้อนกลับเพื่อกำหนดค่า
แต่หากไม่มีเทคโนโลยีเหล่านี้ New จะสร้างอินสแตนซ์ใหม่ผ่านช่องทางปกติ และการเพิ่ม Attributes จะไม่มีผลกระทบใดๆ คุณลักษณะ แตกต่างจากข้อมูลเมตาที่อธิบายไว้ข้างต้น
ข้อมูลเมตาสำหรับคุณสมบัติการพึ่งพา
สามารถระบุได้โดยไม่ซ้ำกันโดยคลาสที่กำหนดคุณสมบัติการพึ่งพา สามารถเปลี่ยนแปลงได้เมื่อคุณสมบัติการพึ่งพาถูกเพิ่มไปยังคลาสอื่น สามารถแทนที่ได้อย่างชัดเจนโดยคลาสที่ได้รับทั้งหมดที่สืบทอดคุณสมบัติการพึ่งพาจากคลาสฐานที่กำหนด ภาษาด้านบนนั้นทื่อ แต่มันอธิบายเจตนาได้แต่เราไม่สามารถเข้าใจความคิดของนักออกแบบในครั้งแรกได้เสมอไป
5. ลักษณะการทำงานพื้นฐานของข้อมูลเมตาของแอตทริบิวต์ ลักษณะการทำงานพื้นฐานของข้อมูลเมตาของแอตทริบิวต์มีฟังก์ชันสามประการสำหรับแอตทริบิวต์ที่ขึ้นต่อกัน นี่เป็นปัญหาที่เพิ่งถูกหยิบยกขึ้นมาในบทความนี้
คุณสมบัติเริ่มต้น คุณสมบัติการแจ้งเตือน คุณสมบัติโทรกลับ ขั้นแรกให้ดูที่ตัวสร้างของ PropertyMetadata ที่สมบูรณ์ หากไม่ได้ตั้งค่าเริ่มต้น PropertyMetadata สำหรับคุณสมบัติที่เป็นอิสระ วัตถุ PropertyMetadata จะถูกสร้างขึ้นโดยอัตโนมัติภายในสำหรับคุณสมบัติที่เป็นอิสระ
สาธารณะ PropertyMetadata (วัตถุ defaultValue, PropertyChangedCallback propertyChangedCallback, CoerceValueCallback coerceValueCallback)
แอ็ตทริบิวต์ที่ขึ้นต่อกันยืมแนวคิดของข้อมูลเมตาของแอททริบิวต์เพื่อทำให้ค่าเริ่มต้นของแอททริบิวต์ การแจ้งเตือนแอททริบิวต์ การบังคับเรียกกลับ และพฤติกรรมอื่น ๆ
1. ค่าเริ่มต้นของแอตทริบิวต์
สาธารณะคงอ่านอย่างเดียว DependencyProperty NameProperty =
DependencyProperty.Register ("ชื่อ", typeof (สตริง), typeof (DPCustomPeople),
ใหม่ PropertyMetadata (string.Empty));
คนส่วนใหญ่จะมีคำถามเมื่อเห็นสิ่งนี้ เหตุใดจึงใช้ PropertyMetadata เพื่อตั้งค่าเริ่มต้น ทำไมไม่ลงทะเบียนโดยตรงในวิธีการ Register
สาธารณะคงอ่านอย่างเดียว DependencyProperty NameProperty =
DependencyProperty.Register ("ชื่อ", typeof (สตริง), typeof (DPCustomPeople),
สตริงว่าง);
แน่นอนว่าคำถามนี้อยู่กับฉันมานานแล้ว และไม่มีอะไรที่ฉันสามารถทำได้หากแก้ไขไม่ได้ ดังนั้นฉันจะทิ้งมันไว้คนเดียวในตอนนี้
หมายเหตุ: เมื่อกำหนดค่าเริ่มต้นให้กับคุณสมบัติใน PropertyMetadata จะไม่สามารถตรวจพบความถูกต้องของประเภทได้
คำจำกัดความดังกล่าว เนื่องจากค่าเริ่มต้นของเซ็กเมนต์โค้ด dp ใน vs คือ 0 จึงเป็นสิ่งที่ควรสังเกต
สาธารณะคงอ่านอย่างเดียว DependencyProperty NameProperty =
DependencyProperty.Register ("ชื่อ", typeof (สตริง), typeof (DPCustomPeople),
UIPropertyMetadata ใหม่ (0));
2. การดำเนินการกู้คืนค่าเริ่มต้นของแอตทริบิวต์
หลังจากกำหนดค่าคุณสมบัติแล้ว คุณสามารถคืนค่าค่าเริ่มต้นโดยใช้เมธอด ClearValue ของ DependencyObject ดังที่แสดงในโค้ดต่อไปนี้
ชื่อสตริงสาธารณะ
-
รับ { กลับ (สตริง) GetValue (NameProperty); }
ตั้งค่า { SetValue (NameProperty, ค่า) }
-
สาธารณะคงอ่านอย่างเดียว DependencyProperty NameProperty =
DependencyProperty.Register ("ชื่อ", typeof (สตริง), typeof (DPCustomPeople),
UIPropertyMetadata ใหม่ (สตริงว่าง));
โมฆะสาธารณะ DPPropertyClearOperator()
-
Console.WriteLine("ชื่อ:" + this.Name);
this.Name = "เทอร์รี่";
Console.WriteLine("ชื่อที่เปลี่ยนชื่อ:" + this.Name);
นี้.ClearValue(NameProperty);
Console.WriteLine("ชื่อ:" + this.Name);
-
ผลลัพธ์เอาท์พุต
หมายเหตุ: แยกความแตกต่างระหว่างการกำหนดค่าเริ่มต้นและค่าเริ่มต้น
โดยปกติการกำหนดค่าเริ่มต้นจะทำใน Constructor แต่นี่ไม่ใช่ค่าเริ่มต้น (ซึ่งเป็นจริงก่อนการมาถึงของคุณสมบัติการพึ่งพา) โดยเฉพาะอย่างยิ่งเมื่อคลาสที่ได้รับมาแทนที่คุณสมบัติ
นักเรียนชั้นสาธารณะ : DPCustomPeople
-
นักเรียนสาธารณะ()
-
this.Name = "ท้องฟ้า";
-
โมฆะสาธารณะ TestSubDefaultDpValue ()
-
Console.WriteLine("ล้างก่อน:"+this.Name);
this.ClearValue (Student.NameProperty);
Console.WriteLine("ล้างหลัง:" + this.Name);
-
-
ผลลัพธ์เอาท์พุต
3.การแจ้งการเปลี่ยนแปลงทรัพย์สิน
ฟังก์ชันนี้เป็นฟังก์ชันที่ใช้บ่อยที่สุด เมื่อค่าคุณสมบัติเปลี่ยนแปลง การเรียกกลับ PropertyChangedCallback จะถูกทริกเกอร์
บูลสาธารณะ IsBoy
-
รับ { กลับ (บูล) GetValue (IsBoyProperty);
ตั้งค่า { SetValue (IsBoyProperty, ค่า }
-
สาธารณะคงที่แบบอ่านอย่างเดียว DependencyProperty IsBoyProperty =
DependencyProperty.Register ("IsBoy", typeof (บูล), typeof (นักเรียน),
UIPropertyMetadata ใหม่ (เท็จ PropertyChangedCallback ใหม่ (IsBoyPropertyChangedCallback)));
โมฆะคงที่สาธารณะ IsBoyPropertyChangedCallback (DependencyObject d, DependencyPropertyChangedEventArgs e)
-
นักเรียน st = d เป็นนักเรียน;
ถ้า (st.IsBoy)
-
Console.WriteLine("สวัสดีเด็กชาย");
-
อื่น
-
Console.WriteLine("สวัสดีสาวน้อย");
-
-
โมฆะสาธารณะ TestPropertyChangedCallback ()
-
this.IsBoy = เท็จ;
this.IsBoy = จริง;
-
คุณสามารถดูผลลัพธ์เอาต์พุตค่าเก่าและค่าใหม่ได้ผ่านทาง DependencyPropertyChangedEventArgs
บันทึก:
(1) จากผลลัพธ์ข้างต้น คุณเห็นไหมว่าค่าเริ่มต้นของคุณสมบัติที่ขึ้นต่อกันจะไม่ทำให้เกิดการแจ้งเตือนการเปลี่ยนแปลงคุณสมบัติ
(2) ทริกเกอร์การแจ้งเตือนการเปลี่ยนแปลงแอตทริบิวต์ด้วยตนเอง
หากคุณต้องการให้ค่าเริ่มต้นทริกเกอร์การเปลี่ยนแปลงคุณสมบัติ (อันที่จริง บางครั้งจำเป็นจริงๆ) คุณไม่จำเป็นต้องรอและทริกเกอร์ด้วยตนเอง
โมฆะส่วนตัว RaiseIsBoyPropertyChangedCallback ()
-
IsBoyPropertyChangedCallback (นี่คือ DependencyPropertyChangedEventArgs. ใหม่)
(Student.IsBoyProperty, Student.IsBoyProperty.DefaultMetadata.DefaultValue, null));
-
(3) เมื่อมีการแจ้งเตือนการเปลี่ยนแปลงคุณลักษณะ ต้องแน่ใจว่าประเภทค่าเริ่มต้นของแอตทริบิวต์ถูกต้อง
เรารู้ว่าประเภทค่ามีค่าเริ่มต้น แต่ประเภทการอ้างอิงไม่มี (นั่นคือ สามารถกำหนดให้เป็นค่าว่างได้) สามารถตรวจสอบได้ว่าประเภทมีประเภทเริ่มต้นหรือไม่โดยใช้คำสำคัญเริ่มต้น
เราเขียนค่าเริ่มต้นของคุณสมบัติการพึ่งพาที่กำหนดไว้ด้านบนเป็น null มันสามารถทำงานได้ดีเมื่อไม่มี PropertyChangedCallback แต่เมื่อมีการเปลี่ยนแปลงคุณสมบัติ ภัยพิบัติเกิดขึ้น และโปรแกรมจะส่งข้อยกเว้นโดยบอกว่าประเภทนั้นไม่ จับคู่.
สาธารณะคงที่แบบอ่านอย่างเดียว DependencyProperty IsBoyProperty =
DependencyProperty.Register ("IsBoy", typeof (บูล), typeof (นักเรียน)
UIPropertyMetadata ใหม่ (null, PropertyChangedCallback ใหม่ (IsBoyPropertyChangedCallback)));
มาดูประเภทการอ้างอิงอีกครั้ง หากค่าเริ่มต้นเป็นโมฆะ ทุกอย่างจะเรียบร้อยดี
IList LovedGirl สาธารณะ
-
รับ { กลับ (IList) GetValue (LovedGirlProperty);
ตั้งค่า { SetValue (LovedGirlProperty, มูลค่า }
-
สาธารณะคงอ่านอย่างเดียว DependencyProperty LovedGirlProperty =
DependencyProperty.Register ("LovedGirl", typeof (IList), typeof (นักเรียน)
UIPropertyMetadata ใหม่ (null, PropertyChangedCallback ใหม่ (LovedGirlChangedCallback)));
โมฆะคงสาธารณะ LovedGirlChangedCallback (DependencyObject d, DependencyPropertyChangedEventArgs e)
-
นักเรียน st = d เป็นนักเรียน;
foreach (รายการ var ใน e.NewValue เป็น IList)
-
Console.WriteLine (รายการ);
-
-
โมฆะสาธารณะ TestReferenceDpType()
-
รายการ<string> รายการ = รายการใหม่<string>();
list.Add("สาว 1");
list.Add("สาว 2");
this.LovedGirl = รายการ;
-
4. บังคับให้เรียกกลับแอตทริบิวต์
ประการแรก ค่าเริ่มต้นยังคงไม่ทริกเกอร์วิธีการโทรกลับ
วิธีการโทรกลับแบบบังคับหมายความว่าไม่ว่าค่าแอตทริบิวต์จะเปลี่ยนแปลงหรือไม่ก็ตาม วิธีการโทรกลับจะถูกป้อน
คะแนน int สาธารณะ
-
รับ { ผลตอบแทน (int) GetValue (ScoreProperty); }
ตั้งค่า { SetValue (ScoreProperty, ค่า) }
-
สาธารณะคงอ่านอย่างเดียว DependencyProperty ScoreProperty =
DependencyProperty.Register ("คะแนน", typeof (int), typeof (นักเรียน),
UIPropertyMetadata ใหม่ (0, null, CoerceValueCallback ใหม่ (ScoreCoerceValueCallback)));
วัตถุคงที่สาธารณะ ScoreCoerceValueCallback (DependencyObject d, object baseValue)
-
Console.WriteLine (ค่าฐาน);
กลับค่าฐาน;
-
โมฆะสาธารณะ TestCoerceValueCallback ()
-
นี่คะแนน = 0;
นี่คะแนน = 0;
นี่คะแนน = 0;
-