كيف يمكنني استخدام ربط البيانات مع أزرار الاختيار Windows Forms؟
-
19-08-2019 - |
سؤال
لدي حقل ثنائي في قاعدة البيانات الخاصة بي يصعب وصفه في واجهة المستخدم باستخدام مربع اختيار واحد من النوع "هل XXXX؟".أفضل استخدام زوج من أزرار الاختيار (على سبيل المثال."افعلها بطريقة Foo" و"افعلها بطريقة Bar")، ولكن في الوقت الحالي جميع الحقول الأخرى في النموذج الخاص بي مرتبطة بالبيانات بكائن أعمال.أرغب في ربط زوج أزرار الاختيار بكائن الأعمال أيضًا، لكن لم أتوصل إلى طريقة جيدة للقيام بذلك بعد.يمكنني ربط أحد الأزرار بالحقل، بحيث يتم تعيين الحقل على "صحيح" إذا تم تحديد الزر، ولكن أثناء تحديد الزر الآخر يتم إلغاء تحديد الزر الأول (أي، يتم إقران زري الاختيار بشكل صحيح )، لا يتم تحديث قيمة الحقل لتعكس ذلك.
أود أن أكون قادرًا على القول
button1.DataBindings.Add(new Binding("checked", source, "useFoo"));
button2.DataBindings.Add(new Binding("checked", source, "!useFoo"));
ولكن أنا متأكد من أن ذلك سوف يرمي عندما يتم تشغيله.هل هناك طريقة أسهل، أم يجب أن أفكر أكثر في كيفية صياغة مربع اختيار واحد؟لا أريد إضافة وظائف إضافية للتعامل مع شيء تافه هذا ...
الوقت المتوقع للوصول:اقترح أحد المعلقين النظر في القائمة المنسدلة (ComboBox).لقد فكرت في هذا، ولكن كيف يمكنني ربط البيانات بحقل منطقي في قاعدة بيانات/خاصية في كائن أعمال؟إذا قمت بربط SelectedItem بخاصية useFoo، فما الذي سيحدث في مجموعة العناصر؟هل يجب أن أضيف فقط "True" و"False"، أو هل يمكنني بطريقة ما إضافة كائن زوج المفتاح/القيمة الذي يربط العنصر المعروض ("Use Foo"/"Do Not Use Foo") بالقيمة المنطقية خلفه؟أواجه مشكلة في العثور على مستندات حول هذا الموضوع.
حول الجواب:كان الحل الذي انتهيت من استخدامه يتضمن تعديل كائن الأعمال - الفكرة الأساسية مشابهة جدًا للفكرة التي نشرها Gurge، لكنني توصلت إليها بشكل منفصل قبل أن أقرأ رده.باختصار، أضفت خاصية منفصلة تعود ببساطة !useFoo
.زر اختيار واحد مرتبط بـ source.UseFoo
, ، والآخر ملزم به source.UseBar
(اسم العقار الجديد).من المهم التأكد من أن الخاصية الجديدة تحتوي على حروف الحروف والحرف، وإلا فسوف ينتهي بك الأمر إلى سلوك غريب حقًا.
المحلول
ولقد وجدت طريقة للقيام بذلك باستخدام مجموعة البيانات / DataTable و.
وأنا جعل عمود محسوب في DataTable مع IIF(Foo=true, false, true)
التعبير. دعونا نسمي ذلك Bar
العمود.
وBar
هو من نوع منطقية. الآن يمكنك ربط RadioButton.Checked
إلى Foo
واحد لBar
.
لتحصل على فحص Bar
/ إلغاء لنشر العودة إلى Foo
يجب أن تذهب إلى رمز DataTable ولدت وإضافة سطر واحد، كان آخرها في هذه العينة:
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public bool Bar {
get {
try {
return ((bool)(this[this.tableradio.BarColumn]));
}
catch (global::System.InvalidCastException e) {
throw new global::System.Data.StrongTypingException("The value for column \'Bar\' in table \'radio\' is DBNull.", e);
}
}
set {
this[this.tableradio.BarColumn] = value;
this[this.tableradio.FooColumn] = !value;
}
}
نصائح أخرى
- ربط
RadioButton
المرتبطة مباشرة بالقيمة المنطقية الخاصة بك (أي يتم تحديدها عندما تكون القيمةtrue
). أضف معالج الأحداث إلى
CheckedChanged
الحدث على هذاRadioButton
يبدو كما يلي:private void radioButton_CheckedChanged(object sender, EventArgs e) { foreach (Binding b in ((Control)sender).DataBindings) b.WriteValue(); }
إذا الكائن عملك تنفذ INotifyPropertyChanged (وهو ما يجعل أجمل عمل ملزم)، يمكنك إضافة التعليمات البرمجية التالية إلى واجهة مرئية حيث BO
هو كائن عملك وأعلن الأساسية WithEvents وBO.Value
هو ملك منطقية كنت ترغب في ربط.
Public Property NotValue() As Boolean
Get
Return Not BO.Value
End Get
Set(ByVal value As Boolean)
BO.Value = Not value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("NotValue"))
End Set
End Property
Private Sub BO_PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Handles BO.PropertyChanged
If e.PropertyName = "Value" Then
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("NotValue"))
End If
End Sub
والارتباطات التالية سوف عقف أزرار الاختيار.
RBTrue.DataBindings.Add(New Binding("Checked", Me.BO, "Value", False, DataSourceUpdateMode.OnPropertyChanged))
RBFalse.DataBindings.Add(New Binding("Checked", Me, "NotValue", False, DataSourceUpdateMode.OnPropertyChanged))
ويجب على واجهة بصرية أيضا تنفيذ INotifyPropertyChanged. هذا الأسلوب يعمل في كلا الاتجاهين: يتم تحديث القيمة الأصلية إذا كانت التغييرات واجهة وإذا تغير القيمة الأصلية واجهة سيتم تحديث بشكل صحيح
وجئت عبر نفس المشكلة، وتبين أنه من الممكن فعلا مع ربط البيانات القياسية:
button1.DataBindings.Add(new Binding("checked", source, "useFoo", false, DataSourceUpdateMode.OnPropertyChanged);
// no need to databind button 2, since button1.checked
// is set to false when button2 is checked
وافتراضيا، يتم تعيين DataSourceUpdateMode
إلى OnValidation
. عن طريق وضع لOnPropertyChanged
، يتم نشر التغيير على الفور إلى كائن ربط بيانات.
وبلدي كائن الأعمال تنفذ INotifyPropertyChanged
؛
وعن طريق اختبار هذا الحل، وجدت أن بلدي الحدث OnPropertyChanged
أقيل مرتين عندما كنت النقر button2
. لمنع هذا، تعيين ببساطة
button1.CausesValidation = false;
button2.CausesValidation = false;
وكما هو موضح هنا: يسبب PropertyChanged الحصول على النار مرتين
هل يدويا في التعليمات البرمجية. عند تحميل النموذج تعيين أزرار الراديو الخاص بك وفقا لقاعدة البيانات الخاصة بك. عند الضغط على "حفظ" مخزن زر دي دولة كما يحلو لك. هذا المثال بتخزين أجهزة الراديو كما حقول بت في قاعدة البيانات.
// Load radio state
radioButton1.Checked = ((myModel)myBindingSource.DataSource).boolOption1;
radioButton2.Checked = ((myModel)myBindingSource.DataSource).boolOption2;
-
// Save radio state
((myModel)myBindingSource.DataSource).boolOption1 = radioButton1.Checked;
((myModel)myBindingSource.DataSource).boolOption2 = radioButton2.Checked;
وحاولت سحب العناصر من لوحة "مصادر البيانات" في Visual Studio 2015 عندما كنت تعرف أزرار بصفتي القيم المنطقية في الجدول ولكن هناك مشاكل مع القيم المنطقية لا يتم تحديثه إلى false عند تحديد زر خيار آخر. عند تغيير "causesValidation" لradiobuttons كاذبة دون رادع تلقائيا عندما قفز بين حقول إدخال النص الأخرى.
هل ينبغي أن يكون فقط لربط واحدة من الضوابط ما دمت التأكد من أنها في نفس المجموعة.
هل يمكن أن نعتبر أيضا المنسدلة.