وبف:إضافة عنصر إلى مجموعة بيانات (خاصية التبعية)
-
21-08-2019 - |
سؤال
لدي هذا DependencyProperty
الذي يحمل كيانًا له خاصية عبارة عن مجموعة (ShoutBox.Entities
):
public static readonly DependencyProperty ShoutBoxProperty = DependencyProperty.Register("ShoutBox",typeof (ShoutBox),typeof (ShoutBoxViewerControl));
public ShoutBox ShoutBox
{
get { return (ShoutBox) GetValue(ShoutBoxProperty); }
set { SetValue(ShoutBoxProperty, value); }
}
يتم ربطه xaml
مثل هذا:
<ItemsControl ItemsSource="{Binding ShoutBox.Entries}">
.
.
</ItemsControl>
عندما أقوم بربطها في المرة الأولى، فإنها تعمل كما هو متوقع ولكن هناك أوقات أحتاج فيها إلى إضافة عناصر إلى المجموعة (بطريقة موجودة في نفس عنصر التحكم)، مثل هذا:
public void AddNewEntry(ShoutBoxEntry newEntry)
{
Dispatcher.Invoke(new Action(() =>{
ShoutBox.Entries.Add(newEntry); //Adding directly the the Dependency property
}));
}
المشكلة هي أنه عندما أقوم بإضافة عنصر جديد بالطريقة المذكورة أعلاه، لا يتم عرض العنصر في ملف ItemsControl
.
سؤالي هو، لماذا لا يتم عرض العنصر الجديد الذي أقوم بإضافته في ملف ItemsControl
?
[يحرر]
Entries
(ShoutBox.Entries) من النوع List<ShoutBoxEntry>
المحلول
ما هو نوع الإدخالات؟يجب أن يكون ObservableCollection أو تطبيق ICollectionChanged.وإلا فلن يعرف الرابط أنه تمت إضافة عنصر جديد.
نصائح أخرى
إن تغيير نوع الإدخالات يجب أن يحل المشكلة بالفعل ...إذا كنت تريد تجنب الاستدعاء الصريح لـ Dispatcher.Invoc، فقد كتبت مجموعة ترفع الحدثين CollectionChanged وPropertyChanged على مؤشر الترابط الذي أنشأ المجموعة:
public class AsyncObservableCollection<T> : ObservableCollection<T>
{
private SynchronizationContext _synchronizationContext = SynchronizationContext.Current;
public AsyncObservableCollection()
{
}
public AsyncObservableCollection(IEnumerable<T> list)
: base(list)
{
}
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (SynchronizationContext.Current == _synchronizationContext)
{
// Execute the CollectionChanged event on the current thread
RaiseCollectionChanged(e);
}
else
{
// Post the CollectionChanged event on the creator thread
_synchronizationContext.Post(RaiseCollectionChanged, e);
}
}
private void RaiseCollectionChanged(object param)
{
// We are in the creator thread, call the base implementation directly
base.OnCollectionChanged((NotifyCollectionChangedEventArgs)param);
}
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (SynchronizationContext.Current == _synchronizationContext)
{
// Execute the PropertyChanged event on the current thread
RaisePropertyChanged(e);
}
else
{
// Post the PropertyChanged event on the creator thread
_synchronizationContext.Post(RaisePropertyChanged, e);
}
}
private void RaisePropertyChanged(object param)
{
// We are in the creator thread, call the base implementation directly
base.OnPropertyChanged((PropertyChangedEventArgs)param);
}
}
مزيد من التفاصيل يمكن العثور عليها هنا :http://www.thomaslevesque.com/2009/04/17/wpf-binding-to-an-asynchronous-collection/