WPF Freezable 錯誤的解決方法?
我最近遇到了一個非常糟糕的 WPF 錯誤。我認為這與Microsoft Connect 上的這個錯誤相同。
我們的應用程序使用 Visual Studio 2010 以 .NET 4.0 客戶端配置文件為目標。
基本上,當 ViewModel 觸發對導致項目在 ItemsControl 中移動的任何屬性或集合的更改時,有可能會引發以下異常。它並不總是發生,而且似乎是基於不同時間的不同觸發器而發生的。似乎更有可能在啟動應用程序後不久。如果您可以使用它幾分鐘而不會遇到異常,那麼您可能永遠不會在該應用程序實例期間遇到異常。
{DynamicResource key}就像Connect錯誤報告一樣,我正在使用SolidColorBrush從ResourceDictionary. 一些字典是手動載入的(用於主題支持)。我嘗試手動凍結這些詞典中的所有內容,但似乎沒有幫助。最近,當我在主視窗中添加了幾個
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 。這似乎在一定程度上減少了異常的數量,但現在我們只是在ObservableCollection’CollectionChanged事件中擊中它們。
要解決此 .net 錯誤,請將程式碼中的所有純色畫筆更改為可凍結。例如
<SolidColorBrush x:Key="WindowBackground" Color="Black" />應改為:
<SolidColorBrush po:Freeze="True" x:Key="WindowBackground" Color="Black" />.有關更詳細的說明,請參見此處:如何在 XAML 中凍結從 Freezable 派生的 WPF 對象?.