‏הצגת רשומות עם תוויות WPF. הצג את כל הרשומות
‏הצגת רשומות עם תוויות WPF. הצג את כל הרשומות

יום שני, 7 במרץ 2011

פתרון אפשרי לבעיית ביצועים ב TreeView

בעיית performance חמורה כשניסיתי לעשות custom tree view + data binding להרבה נתונים.

בסופו של דבר התברר לי שה virtualization של ה TreeView נדפק כאשר מורידים trigger שמגיע ב default template של TreeViewItem

מה שגרם לייצור של כל ה TreeViewItems בפעם הראשונה בבת אחת.

התיקון הוא ב style של TreeViewItem (או מה שיורש ממנו) שמתחיל ב:

<Style TargetType="{x:Type TreeViewItem}">

באזור ה triggers

<ControlTemplate.Triggers>

חייבים להשאיר את השורות הבאות (או multi trigger וכו' שדואג שזאת תהיה התוצאה):

<Trigger Property="IsExpanded" Value="false">
    <Setter Property="Visibility" TargetName="ItemsHost" Value="Collapsed"/>
</Trigger>



במצב הזה העץ לא ייצור את הילדים של הענפים בעץ עד שיפתחו אותם ע"י Expand

יום חמישי, 10 בפברואר 2011

ObservableDictionary of Dr WPF with dispatcher support

אני משתמש הרבה פעמים ב ObservableDictionary של DR WPF

היתה לי בעיה שחוזרת על עצמה כאשר מוסיפים או מורידים איברים מה dictionary ב thread אחר , הוא זורק את ה CollectionChanged / PropertyChanged על אותו thread שבוא נעשה השינוי וזה מה שגורם ל exception:

"InvalidOperationException: The calling thread cannot access this object because a different thread owns it."

כדי לתת תמיכה מתוך ה ObservableDictionary עשיתי לו שינוי קטן שתומך בזריקת ה events על ה dispatcher הנכון:

1. הוספת dispatcher ו DispatcherPriority ל ctor's – כפרמטרים אופציונאליים


public ObservableDictionary(Dispatcher dispatcher = null,DispatcherPriority dispatcherPriority = DispatcherPriority.DataBind)
{
    _dispatcher = dispatcher;
    _dispatcherPriority = dispatcherPriority;
    _keyedEntryCollection = new KeyedDictionaryEntryCollection<TKey>();
}

2. במתודות OnCollectionChanged ו OnPropertyChanged אם יש dispatcher משתמשים בו כדי להעלות את ה  event על הUI thread הנכון.

protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
{
    var handler = CollectionChanged;
    if (handler != null)
    {
    if (_dispatcher != null)
    {
        if (_dispatcher.CheckAccess())
        {
            handler(this, args);
        }
        else
        {
            _dispatcher.Invoke((Action)(() => handler(this, args)), _dispatcherPriority);
        }
    }
    else
    {
        handler(this, args);
    }
    }
}

ניתן להוריד את הקוד מכאן