ผูกกล่องข้อความเข้ากับพจนานุกรมโดยใช้คีย์ตัวแปร

ฉันต้องการใช้ UI แบบไดนามิกโดยที่ตัวควบคุมกล่องข้อความจะถูกสร้างขึ้นแบบไดนามิกและเนื้อหาเชื่อมโยงกับพจนานุกรมบน ViewModel

ฉันกำลังพยายามใช้การเชื่อมโยงข้อมูลแบบสองทางโดยใช้ ReactiveUI

ปัญหาที่ฉันกำลังเผชิญคือดูเหมือนว่าฉันจะได้รับอนุญาตให้ผูกกล่องข้อความกับรายการในพจนานุกรมเท่านั้นหากฉันใช้สตริงตัวอักษรเป็นคีย์ แต่ทันทีที่ฉันพยายามใช้ตัวแปรสตริงเพื่อตั้งค่าการเชื่อมโยง ฉันได้รับข้อผิดพลาดต่อไปนี้:

Index expressions are only supported with constants.

นี่คือตัวอย่างง่ายๆ ของสิ่งที่ฉันพยายามทำ กล่องข้อความไม่ได้สร้างอินสแตนซ์แบบไดนามิกเพื่อแยกปัญหา:

string PropNum = "22017";
this.Bind(ViewModel, vm => vm.ExcelData[PropNum], view => view.tbCreate.Text);

ในตัวอย่างนี้ ExcelData คือ Dictionary<string, object> ที่กำหนดไว้ใน ViewModel

ในทางกลับกัน งานต่อไปนี้ใช้ได้ดี:

this.Bind(ViewModel, vm => vm.ExcelData["22017"], view => view.tbCreate.Text);

ฉันต้องการให้คีย์การค้นหาเป็นตัวแปร มีวิธีใดบ้างที่จะบรรลุผลนี้?

ขอบคุณ


person Luc Morin    schedule 22.08.2018    source แหล่งที่มา


คำตอบ (1)


ไม่คุณไม่สามารถทำสิ่งที่คุณต้องการด้วย Bind()

เราใช้ Expression> เพื่อกำหนดว่าการเชื่อมโยงควรมาจากไหน ตามที่ข้อความแสดงข้อผิดพลาดแจ้งว่าคุณต้องใช้ค่าคงที่หากคุณต้องการใช้ดัชนี

เพื่อให้คุณเห็นภาพว่า Expression กำลังทำอะไรอยู่ Expression อนุญาตให้คุณใช้รายละเอียดเกี่ยวกับ lambda ที่ผู้ใช้ให้มา

this.Bind(this.ViewModel, vm => vm.Property1.Property2.Property3)

ด้วย Expression คุณจะได้รับรายละเอียดเกี่ยวกับคุณสมบัติ/วัตถุแต่ละรายการตลอดทาง

สิ่งที่เราทำคือสมัครสมาชิกแต่ละออบเจ็กต์ตามเหตุการณ์ PropertyChanged ของทาง (หากออบเจ็กต์ไม่เป็นโมฆะ) และเราจะตั้งค่าให้กับคุณสมบัติอื่นอย่างเหมาะสมด้วย

นิพจน์มีข้อจำกัดที่จะต้องคงที่ เนื่องจากส่วนใหญ่เป็นฟีเจอร์เวลาคอมไพล์

ในแง่ของสิ่งที่คุณต้องการบรรลุ คุณจะต้องทำทุกอย่างหลังจากมูลค่าไดนามิกของคุณ ดังนั้นคุณจึงสามารถสมัครรับเหตุการณ์ PropertyChange ได้เมื่อคุณแก้ไขดัชนี ExcelData แล้ว

คุณสามารถใช้ WhenAnyValue() บนวัตถุที่ได้รับการแก้ไข

myViewModel.ExcelData[propertyIndex].WhenAnyValue(x => x.Value).BindTo(this.ViewModel, view => view.TextBox.Text);
this.WhenAnyValue(view => view.TextBox.Text).BindTo(myViewModel.ExcelData[propertyIndex], x => x.Value);

คุณต้องใช้ BindTo สองตัวเนื่องจากเป็น OneWayOnly และฉันได้ใช้สมมติฐานที่คุณมีคุณสมบัติ Value บนวัตถุ ExcelData ของคุณ

โปรดทราบว่าวัตถุ ExcelData ของคุณที่มีอยู่ใน propertyIndex จะต้องได้รับมาจาก INotifyPropertyChanged

person Glenn Watson    schedule 22.08.2018
comment
ฉันอาจผิดและเอกสารก็ไม่ชัดเจน 100% เกี่ยวกับเรื่องนี้ แต่ BindTo มีผลผูกพันทางเดียวเท่านั้นไม่ใช่หรือ - person Luc Morin; 22.08.2018
comment
ใช่ ถูกต้องแต่ไม่มีอะไรหยุดคุณไม่ให้ทำสองข้อความ สิ่งที่ Bind/WhenAnyValue ทำคือ Expression‹T› ซึ่งพวกเขาจะอ่านแต่ละคุณสมบัติที่มีอยู่ภายในและสมัครรับการเปลี่ยนแปลงคุณสมบัติ (เรามีกลไกที่ช่วยให้เราตรวจจับกลไกการผูกที่ดีที่สุด) เทคนิคการใช้ค่าไม่คงที่ของคุณจะใช้ไม่ได้ผล ดังนั้นคุณจึงเหลือแค่การสร้างห่วงโซ่นั้นด้วยตัวเองอย่างมีประสิทธิภาพ และคุณสามารถทำได้โดยการทำ WhenAnyValue chains ในอดีตฉันได้สร้างวิธีการขยายเพื่อช่วยในสถานการณ์ประเภทนี้ - person Glenn Watson; 22.08.2018
comment
ฉันเคยเห็นการโอเวอร์โหลดโดยใช้ Expression แต่ฉันยอมรับว่าฉันต้องดูตัวอย่างเพื่อทำความเข้าใจวิธีใช้งาน คุณสามารถแก้ไขคำตอบของคุณด้วยโค้ดตัวอย่างบางส่วนได้หรือไม่? - person Luc Morin; 22.08.2018
comment
คำตอบคือคำตอบ สิ่งที่คุณต้องการไม่สามารถทำได้ด้วย Bind() คุณจะต้องใช้กลไกอื่นเพื่อรับการอัปเดตคุณสมบัติ - person Glenn Watson; 22.08.2018
comment
ฉันเห็นด้วย แต่ฉันพยายามรับคำแนะนำ ViewModel.ExcelData[Row].WhenAnyValue() ของคุณให้ได้ผลแต่ไม่ประสบผลสำเร็จ ไม่มีอะไรถูกกระตุ้น หากคุณเคยทำสิ่งที่คล้ายกันในอดีต คุณช่วยอัปเดตคำตอบของคุณด้วยโค้ดบางส่วนได้ไหม - person Luc Morin; 22.08.2018
comment
คำตอบที่แก้ไขช่วยได้หรือไม่? - person Glenn Watson; 22.08.2018
comment
ฉันเดาว่าประโยคสุดท้ายของคุณตอกย้ำฉัน ตามที่กล่าวไว้ใน OP ของฉัน ExcelData เป็นประเภท Dictionary<string, object> ดังนั้นจึงไม่มี INPC ฉันต้องคิดใหม่เกี่ยวกับแนวทางของฉันหากจำเป็นต้องใช้ INPC - person Luc Morin; 22.08.2018
comment
สิ่งที่ตลกก็คือ Bind ใช้คีย์ตัวอักษร รับการเปลี่ยนแปลงในออบเจ็กต์แม้ว่าจะไม่ได้ใช้ INPC ก็ตาม - person Luc Morin; 22.08.2018
comment
ใช่ BindTo() จะรับการเปลี่ยนแปลงค่าแล้วผูกเท่านั้น Bind() จะจับค่าเริ่มต้นสำหรับประเภท POCO ด้วย คุณสามารถบรรลุสิ่งเดียวกันได้โดยการตั้งค่าให้กับการควบคุมเป้าหมายของคุณโดยตรง - person Glenn Watson; 22.08.2018
comment
Glenn สิ่งที่คุณพูดเกี่ยวกับการเก็บค่าเริ่มต้นนั้นน่าสนใจมาก คุณรู้จักแหล่งข้อมูลที่จะช่วยให้ฉันเรียนรู้เกี่ยวกับความรู้ที่ซ่อนอยู่เกี่ยวกับ RxUI หรือไม่ ฉันไม่รังเกียจที่จะซื้อหนังสือถ้าจำเป็น - person Luc Morin; 23.08.2018
comment
Kent Boogart (หนึ่งในผู้ดูแล RxUI ของฉัน) เปิดตัวหนังสือเมื่อต้นปีนี้ ควรค่าแก่การคัดลอกและผ่านเทคนิคเหล่านี้มากมาย kent-boogaart.com/you -i-และ-reactiveui - person Glenn Watson; 23.08.2018