2011-08-22 13 views
27

最近、私は本当に悪いWPFバグにぶつかってきました。私は、Microsoft Connectのthis bugと同じだと思います。 ViewModelにはItemsControlに内を移動するためのアイテムを引き起こす任意のプロパティまたはコレクションへの変更をトリガすると、2010年WPF Freezableバグの回避策?

基本的にはVisual Studioを使用

当社のアプリケーションのターゲット.NET 4.0クライアントのプロファイルは、例外はそのチャンスがあります以下が投げられる。それはいつも起こるとは限らず、違う時期に異なるトリガーに基づいて起こるようです。アプリケーションを起動した直後の可能性が高いようです。例外を叩かずに数分間使用することができれば、おそらくそのアプリケーションインスタンス中にヒットすることはありません。

Connectバグレポートと同様に、私は{DynamicResource key}を使用してResourceDictionaryからSolidColorBrushをロードしています。いくつかの辞書は手動で読み込まれます(テーマサポートのため)。私は手動でそれらの辞書のすべてを凍結しようとしましたが、それは助けには見えません。

UserControlをメインウィンドウに追加したときに例外が頻繁に発生しました。その中には、ItemsControlsがObservableCollectionにバインドされています。以前は、50回中に例外1回しか見ませんでしたが、今は5回のうち4回、プログラムを使用しています。

回避策の候補がありますか? Connectのバグは、これが次の.NETリリースで修正される可能性があることを示していますが、このバグは今では基本的にアプリケーションを使用できなくしています。

 
    System.InvalidOperationException: Specified value of type 'System.Windows.Media.SolidColorBrush' must have IsFrozen set to false to modify. 
     at System.Windows.Freezable.WritePreamble() 
     at System.Windows.Freezable.remove_Changed(EventHandler value) 
     at System.Windows.ResourceReferenceExpression.ResourceReferenceExpressionWeakContainer.RemoveChangedHandler() 
     at System.Windows.ResourceReferenceExpression.ResourceReferenceExpressionWeakContainer.InvalidateTargetSubProperty(Object sender, EventArgs args) 
     at System.Windows.Freezable.FireChanged() 
     at System.Windows.Freezable.Freeze(Boolean isChecking) 
     at System.Windows.Freezable.Freeze() 
     at System.Windows.Freezable.System.Windows.ISealable.Seal() 
     at System.Windows.StyleHelper.SealIfSealable(Object value) 
     at System.Windows.StyleHelper.GetChildValueHelper(UncommonField`1 dataField, ItemStructList`1& valueLookupList, DependencyProperty dp, DependencyObject container, FrameworkObject child, Int32 childIndex, Boolean styleLookup, EffectiveValueEntry& entry, ValueLookupType& sourceType, FrameworkElementFactory templateRoot) 
     at System.Windows.StyleHelper.GetChildValue(UncommonField`1 dataField, DependencyObject container, Int32 childIndex, FrameworkObject child, DependencyProperty dp, FrugalStructList`1& childRecordFromChildIndex, EffectiveValueEntry& entry, ValueLookupType& sourceType, FrameworkElementFactory templateRoot) 
     at System.Windows.StyleHelper.GetValueFromTemplatedParent(DependencyObject container, Int32 childIndex, FrameworkObject child, DependencyProperty dp, FrugalStructList`1& childRecordFromChildIndex, FrameworkElementFactory templateRoot, EffectiveValueEntry& entry) 
     at System.Windows.FrameworkElement.GetValueFromTemplatedParent(DependencyProperty dp, EffectiveValueEntry& entry) 
     at System.Windows.FrameworkElement.GetRawValue(DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry& entry) 
     at System.Windows.FrameworkElement.EvaluateBaseValueCore(DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry& newEntry) 
     at System.Windows.DependencyObject.EvaluateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry newEntry, OperationType operationType) 
     at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) 
     at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp) 
     at System.Windows.StyleHelper.InvalidateResourceDependentsForChild(DependencyObject container, DependencyObject child, Int32 childIndex, ResourcesChangeInfo info, FrameworkTemplate parentTemplate) 
     at System.Windows.TreeWalkHelper.InvalidateStyleAndReferences(DependencyObject d, ResourcesChangeInfo info, Boolean containsTypeOfKey) 
     at System.Windows.TreeWalkHelper.OnResourcesChanged(DependencyObject d, ResourcesChangeInfo info, Boolean raiseResourceChangedEvent) 
     at System.Windows.FrameworkElement.OnAncestorChangedInternal(TreeChangeInfo parentTreeState) 
     at System.Windows.TreeWalkHelper.OnAncestorChanged(DependencyObject d, TreeChangeInfo info) 
     at System.Windows.DescendentsWalker`1._VisitNode(DependencyObject d) 
     at MS.Internal.PrePostDescendentsWalker`1._VisitNode(DependencyObject d) 
     at System.Windows.DescendentsWalker`1.VisitNode(FrameworkElement fe) 
     at System.Windows.DescendentsWalker`1.VisitNode(DependencyObject d) 
     at System.Windows.DescendentsWalker`1.WalkFrameworkElementLogicalThenVisualChildren(FrameworkElement feParent, Boolean hasLogicalChildren) 
     at System.Windows.DescendentsWalker`1.IterateChildren(DependencyObject d) 
     at System.Windows.DescendentsWalker`1.StartWalk(DependencyObject startNode, Boolean skipStartNode) 
     at MS.Internal.PrePostDescendentsWalker`1.StartWalk(DependencyObject startNode, Boolean skipStartNode) 
     at System.Windows.TreeWalkHelper.InvalidateOnTreeChange(FrameworkElement fe, FrameworkContentElement fce, DependencyObject parent, Boolean isAddOperation) 
     at System.Windows.FrameworkElement.OnVisualParentChanged(DependencyObject oldParent) 
     at System.Windows.Media.Visual.FireOnVisualParentChanged(DependencyObject oldParent) 
     at System.Windows.Media.Visual.RemoveVisualChild(Visual child) 
     at System.Windows.Media.VisualCollection.DisconnectChild(Int32 index) 
     at System.Windows.Media.VisualCollection.Clear() 
     at System.Windows.Controls.UIElementCollection.ClearInternal() 
     at System.Windows.Controls.Panel.ClearChildren() 
     at System.Windows.Controls.Panel.OnItemsChangedInternal(Object sender, ItemsChangedEventArgs args) 
     at System.Windows.Controls.Panel.OnItemsChanged(Object sender, ItemsChangedEventArgs args) 
     at System.Windows.Controls.ItemContainerGenerator.OnRefresh() 
     at System.Windows.Controls.ItemContainerGenerator.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args) 
     at System.Windows.Controls.ItemContainerGenerator.System.Windows.IWeakEventListener.ReceiveWeakEvent(Type managerType, Object sender, EventArgs e) 
     at System.Windows.WeakEventManager.DeliverEventToList(Object sender, EventArgs args, ListenerList list) 
     at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args) 
     at System.Collections.Specialized.CollectionChangedEventManager.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args) 
     at System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e) 
     at System.Windows.Data.CollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs args) 
     at System.Windows.Controls.ItemCollection.System.Windows.IWeakEventListener.ReceiveWeakEvent(Type managerType, Object sender, EventArgs e) 
     at System.Windows.WeakEventManager.DeliverEventToList(Object sender, EventArgs args, ListenerList list) 
     at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args) 
     at System.Collections.Specialized.CollectionChangedEventManager.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args) 
     at System.Windows.Data.CollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs args) 
     at System.Windows.Data.ListCollectionView.RefreshOverride() 
     at System.Windows.Data.CollectionView.Refresh() 
     at System.Windows.Data.CollectionView.EndDefer() 
     at System.Windows.Data.CollectionView.DeferHelper.Dispose() 
     at System.Windows.Controls.ItemCollection.SetCollectionView(CollectionView view) 
     at System.Windows.Controls.ItemCollection.SetItemsSource(IEnumerable value) 
     at System.Windows.Controls.ItemsControl.OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e) 
     at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e) 
     at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args) 
     at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) 
     at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp) 
     at System.Windows.Data.BindingExpressionBase.Invalidate(Boolean isASubPropertyChange) 
     at System.Windows.Data.BindingExpression.TransferValue(Object newValue, Boolean isASubPropertyChange) 
     at System.Windows.Data.BindingExpression.ScheduleTransfer(Boolean isASubPropertyChange) 
     at MS.Internal.Data.ClrBindingWorker.NewValueAvailable(Boolean dependencySourcesChanged, Boolean initialValue, Boolean isASubPropertyChange) 
     at MS.Internal.Data.PropertyPathWorker.UpdateSourceValueState(Int32 k, ICollectionView collectionView, Object newValue, Boolean isASubPropertyChange) 
     at MS.Internal.Data.ClrBindingWorker.OnSourcePropertyChanged(Object o, String propName) 
     at MS.Internal.Data.PropertyPathWorker.System.Windows.IWeakEventListener.ReceiveWeakEvent(Type managerType, Object sender, EventArgs e) 
     at System.Windows.WeakEventManager.DeliverEventToList(Object sender, EventArgs args, ListenerList list) 
     at System.ComponentModel.PropertyChangedEventManager.OnPropertyChanged(Object sender, PropertyChangedEventArgs args) 
     at ***.ViewModelBase.OnPropertyChanged(String name) in c:\***\ViewModelBase.cs:line 17 
    ..... 

EDIT: 我々は、単に私たちのViewModel基本クラスのPropertyChangedイベントの内部でスローされたInvalidOperationExceptionのを抑制しようとしました。それは例外の数を幾分減らすように見えましたが、今ではObservableCollectionCollectionChangedイベントでそれらをヒットしました。

+0

Dispatcher.Invokeを使用して、別の優先順位でOnPropertyChangedをコード内で呼び出そうとしましたか?それはときどき私が影響を与えるために使用するものです - 少しランダムに私は同意します:-)競合条件のWPF ... –

+2

野生の推測ですが、インスタンス化時に参照されているブラシリソースをすべてフリーズできますか?あなたはここでそれを行う方法を読むことができます:http://stackoverflow.com/questions/799890/how-can-wpf-objects-deriving-from-freezable-be-frozen-in-xaml –

+0

また、 ObservableCollectionをUIスレッドから変更するだけですか? –

答えて

20

解決方法この.netバグは、コード内のすべてのソリッドカラーブラシをフリーズ可能に変更します。例えば

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

は、次のように変更します。手順の詳細については

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

こちらをご覧ください:How can WPF objects deriving from Freezable be frozen in XAML?

+0

これはそれを修正したようです!私は辞書を読み込むときに私の手動のフリーズが完全には機能していないと思います。 –

+0

すごい!どのように簡単に、完全に私を助けた。 –

+2

"po"は何ですか? – tofutim

0

ItemsControlと派生したコントロールを持つMVVMに関するバグのある動作になるたびに、私の最初の試みはVirtualizingStackPanelを無効にすることです。

<ItemsControl VirtualizingStackPanel.IsVirtualizing="False" /> 

ただ、試して...

+1

私はこれを試して、アプリケーションのすべてのComboBox/ItemsControl/ListBoxでこれを設定しました。それは違いを生じさせるようではありません。 –

3

私はこのための回避策があると信じていません。私が読んだことから、これを自分自身で処理しなければならないため、WPFは作成時にリソースを自動的にフリーズします。したがって、そのリソースでDynamicResourceを使用しようとするたびに、フリーズ可能な例外が発生します。ここで

何が起こっているかで、Microsoft Foundationのチームからの引用です:

「「WPFは、スタイルと テンプレートが複数のスレッドで使用することができ、スタイルやテンプレート内の任意のfreezablesを凍結する、とfreezablesができます。 t がフリーズしている場合を除き、現在のところ、アプリケーションのリソース内に を置くことにこれを拡張することを検討しています。 フリーズすることができるので、フリーズしたフリーズのDynamicResourceは機能しません潜在的に複数の親を持っている - それは曖昧です 私たちはr食べる。

+0

'Freezable'がフリーズしているときの' DynamicResource'は、アプリケーションが起動し、時間の大部分をうまく動作します。私が参照しているリソースは、その内部に動的または静的なリソース参照を持たないブラシのようなものだけです。それらはすべて次のようになります: '' また、私が知る限り、WPFは辞書が読み込まれると直ちに物事を自動的にフリーズしていないようです。それが私が手動でフリーズする理由です。 –

関連する問題