Dot-Net

WPF Freezable 錯誤的解決方法?

  • August 22, 2011

我最近遇到了一個非常糟糕的 WPF 錯誤。我認為這與Microsoft Connect 上的這個錯誤相同。

我們的應用程序使用 Visual Studio 2010 以 .NET 4.0 客戶端配置文件為目標。

基本上,當 ViewModel 觸發對導致項目在 ItemsControl 中移動的任何屬性或集合的更改時,有可能會引發以下異常。它並不總是發生,而且似乎是基於不同時間的不同觸發器而發生的。似乎更有可能在啟動應用程序後不久。如果您可以使用它幾分鐘而不會遇到異常,那麼您可能永遠不會在該應用程序實例期間遇到異常。

{DynamicResource key}就像Connect錯誤報告一樣,我正在使用SolidColorBrushResourceDictionary. 一些字典是手動載入的(用於主題支持)。我嘗試手動凍結這些詞典中的所有內容,但似乎沒有幫助。

最近,當我在主視窗中添加了幾個UserControls 並將其中的 ItemsControls 綁定到ObservableCollections 時,異常變得更加頻繁。以前,我只會在 50 次中看到異常 1 次,但現在我在使用該程序的 5 次中看到了 4 次。

有沒有人對解決方法有任何想法?Connect 錯誤表明這可能會在下一個 .NET 版本(無論何時)中得到修復,但這個錯誤使我們的應用程序現在基本上無法使用。

System.InvalidOperationException:“System.Windows.Media.SolidColorBrush”類型的指定值必須將 IsFrozen 設置為 false 才能修改。
在 System.Windows.Freezable.WritePreamble()
在 System.Windows.Freezable.remove_Changed(EventHandler 值)
在 System.Windows.ResourceReferenceExpression.ResourceReferenceExpressionWeakContainer.RemoveChangedHandler()
在 System.Windows.ResourceReferenceExpression.ResourceReferenceExpressionWeakContainer.InvalidateTargetSubProperty(對象發件人,EventArgs args)
在 System.Windows.Freezable.FireChanged()
在 System.Windows.Freezable.Freeze(布爾 isChecking)
在 System.Windows.Freezable.Freeze()
在 System.Windows.Freezable.System.Windows.ISealable.Seal()
在 System.Windows.StyleHelper.SealIfSealable(對象值)
在 System.Windows.StyleHelper.GetChildValueHelper(UncommonField`1 dataField,ItemStructList`1& valueLookupList,DependencyProperty dp,DependencyObject 容器,FrameworkObject 子項,Int32 childIndex,布爾樣式查找,EffectiveValueEntry& 條目,ValueLookupType& sourceType,FrameworkElementFactory templateRoot)
在 System.Windows.StyleHelper.GetChildValue(UncommonField`1 數據欄位,DependencyObject 容器,Int32 childIndex,FrameworkObject 子項,DependencyProperty dp,FrugalStructList`1& childRecordFromChildIndex,EffectiveValueEntry& 條目,ValueLookupType& sourceType,FrameworkElementFactory templateRoot)
在 System.Windows.StyleHelper.GetValueFromTemplatedParent(DependencyObject 容器、Int32 childIndex、FrameworkObject 子項、DependencyProperty dp、FrugalStructList`1& childRecordFromChildIndex、FrameworkElementFactory templateRoot、EffectiveValueEntry& 條目)
在 System.Windows.FrameworkElement.GetValueFromTemplatedParent(DependencyProperty dp,EffectiveValueEntry& 條目)
在 System.Windows.FrameworkElement.GetRawValue(DependencyProperty dp,PropertyMetadata 元數據,EffectiveValueEntry& 條目)
在 System.Windows.FrameworkElement.EvaluateBaseValueCore(DependencyProperty dp,PropertyMetadata 元數據,EffectiveValueEntry & newEntry)
在 System.Windows.DependencyObject.EvaluateEffectiveValue(EntryIndex entryIndex,DependencyProperty dp,PropertyMetadata 元數據,EffectiveValueEntry oldEntry,EffectiveValueEntry newEntry,OperationType operationType)
在 System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex、DependencyProperty dp、PropertyMetadata 元數據、EffectiveValueEntry oldEntry、EffectiveValueEntry& newEntry、Boolean coerceWithDeferredReference、Boolean coerceWithCurrentValue、OperationType operationType)
在 System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp)
在 System.Windows.StyleHelper.InvalidateResourceDependentsForChild(DependencyObject 容器,DependencyObject 子項,Int32 childIndex,ResourcesChangeInfo 資訊,FrameworkTemplate parentTemplate)
在 System.Windows.TreeWalkHelper.InvalidateStyleAndReferences(DependencyObject d,ResourcesChangeInfo 資訊,布爾 containsTypeOfKey)
在 System.Windows.TreeWalkHelper.OnResourcesChanged(DependencyObject d,ResourcesChangeInfo 資訊,布爾 raiseResourceChangedEvent)
在 System.Windows.FrameworkElement.OnAncestorChangedInternal(TreeChangeInfo parentTreeState)
在 System.Windows.TreeWalkHelper.OnAncestorChanged(DependencyObject d,TreeChangeInfo 資訊)
在 System.Windows.DescendentsWalker`1._VisitNode(DependencyObject d)
在 MS.Internal.PrePostDescendentsWalker`1._VisitNode(DependencyObject d)
在 System.Windows.DescendentsWalker`1.VisitNode(FrameworkElement fe)
在 System.Windows.DescendentsWalker`1.VisitNode(DependencyObject d)
在 System.Windows.DescendentsWalker`1.WalkFrameworkElementLogicalThenVisualChildren(FrameworkElement feParent, Boolean hasLogicalChildren)
在 System.Windows.DescendentsWalker`1.IterateChildren(DependencyObject d)
在 System.Windows.DescendentsWalker`1.StartWalk (DependencyObject startNode, Boolean skipStartNode)
在 MS.Internal.PrePostDescendentsWalker`1.StartWalk (DependencyObject startNode, Boolean skipStartNode)
在 System.Windows.TreeWalkHelper.InvalidateOnTreeChange(FrameworkElement fe,FrameworkContentElement fce,DependencyObject 父級,布爾 isAddOperation)
在 System.Windows.FrameworkElement.OnVisualParentChanged(DependencyObject oldParent)
在 System.Windows.Media.Visual.FireOnVisualParentChanged(DependencyObject oldParent)
在 System.Windows.Media.Visual.RemoveVisualChild(視覺孩子)
在 System.Windows.Media.VisualCollection.DisconnectChild(Int32 索引)
在 System.Windows.Media.VisualCollection.Clear()
在 System.Windows.Controls.UIElementCollection.ClearInternal()
在 System.Windows.Controls.Panel.ClearChildren()
在 System.Windows.Controls.Panel.OnItemsChangedInternal(對象發送者,ItemsChangedEventArgs 參數)
在 System.Windows.Controls.Panel.OnItemsChanged(對象發送者,ItemsChangedEventArgs args)
在 System.Windows.Controls.ItemContainerGenerator.OnRefresh()
在 System.Windows.Controls.ItemContainerGenerator.OnCollectionChanged(對象發送者,NotifyCollectionChangedEventArgs 參數)
在 System.Windows.Controls.ItemContainerGenerator.System.Windows.IWeakEventListener.ReceiveWeakEvent(類型 managerType,對象發送者,EventArgs e)
在 System.Windows.WeakEventManager.DeliverEventToList(對象發送者,EventArgs 參數,ListenerList 列表)
在 System.Windows.WeakEventManager.DeliverEvent(對象發送者,EventArgs 參數)
在 System.Collections.Specialized.CollectionChangedEventManager.OnCollectionChanged(對象發送者,NotifyCollectionChangedEventArgs 參數)
在 System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(對象發送者,NotifyCollectionChangedEventArgs e)
在 System.Windows.Data.CollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs 參數)
在 System.Windows.Controls.ItemCollection.System.Windows.IWeakEventListener.ReceiveWeakEvent(類型 managerType,對象發送者,EventArgs e)
在 System.Windows.WeakEventManager.DeliverEventToList(對象發送者,EventArgs 參數,ListenerList 列表)
在 System.Windows.WeakEventManager.DeliverEvent(對象發送者,EventArgs 參數)
在 System.Collections.Specialized.CollectionChangedEventManager.OnCollectionChanged(對象發送者,NotifyCollectionChangedEventArgs 參數)
在 System.Windows.Data.CollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs 參數)
在 System.Windows.Data.ListCollectionView.RefreshOverride()
在 System.Windows.Data.CollectionView.Refresh()
在 System.Windows.Data.CollectionView.EndDefer()
在 System.Windows.Data.CollectionView.DeferHelper.Dispose ()
在 System.Windows.Controls.ItemCollection.SetCollectionView(CollectionView 視圖)
在 System.Windows.Controls.ItemCollection.SetItemsSource(IEnumerable 值)
在 System.Windows.Controls.ItemsControl.OnItemsSourceChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
在 System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
在 System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
在 System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs 參數)
在 System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex、DependencyProperty dp、PropertyMetadata 元數據、EffectiveValueEntry oldEntry、EffectiveValueEntry& newEntry、Boolean coerceWithDeferredReference、Boolean coerceWithCurrentValue、OperationType operationType)
在 System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp)
在 System.Windows.Data.BindingExpressionBase.Invalidate(布爾 isASubPropertyChange)
在 System.Windows.Data.BindingExpression.TransferValue(對象 newValue,布爾 isASubPropertyChange)
在 System.Windows.Data.BindingExpression.ScheduleTransfer(布爾 isASubPropertyChange)
在 MS.Internal.Data.ClrBindingWorker.NewValueAvailable(布爾依賴源更改,布爾初始值,布爾 isASubPropertyChange)
在 MS.Internal.Data.PropertyPathWorker.UpdateSourceValueState(Int32 k,ICollectionView 集合視圖,對象 newValue,布爾 isASubPropertyChange)
在 MS.Internal.Data.ClrBindingWorker.OnSourcePropertyChanged(對象 o,字元串 propName)
在 MS.Internal.Data.PropertyPathWorker.System.Windows.IWeakEventListener.ReceiveWeakEvent(類型 managerType,對象發送者,EventArgs e)
在 System.Windows.WeakEventManager.DeliverEventToList(對象發送者,EventArgs 參數,ListenerList 列表)
在 System.ComponentModel.PropertyChangedEventManager.OnPropertyChanged(對象發送者,PropertyChangedEventArgs 參數)
在 c:\***\ViewModelBase.cs:line 17 中的 ***.ViewModelBase.OnPropertyChanged(String name)
.....

編輯:我們還嘗試簡單地抑制InvalidOperationException在 ViewModel 基類的 PropertyChanged 事件中拋出的任何 s 。這似乎在一定程度上減少了異常的數量,但現在我們只是在ObservableCollectionCollectionChanged事件中擊中它們。

要解決此 .net 錯誤,請將程式碼中的所有純色畫筆更改為可凍結。例如

<SolidColorBrush x:Key="WindowBackground" Color="Black" />

應改為:

<SolidColorBrush po:Freeze="True" x:Key="WindowBackground" Color="Black" />. 

有關更詳細的說明,請參見此處:如何在 XAML 中凍結從 Freezable 派生的 WPF 對象?.

引用自:https://stackoverflow.com/questions/7148764