31

私は最近、本当にひどい WPF バグに遭遇しました。Microsoft Connectのこのバグと同じだと思います。

このアプリケーションは、Visual Studio 2010 を使用して .NET 4.0 Client Profile をターゲットにしています。

基本的に、ViewModel が ItemsControl 内で項目を移動させるプロパティまたはコレクションへの変更をトリガーすると、以下の例外がスローされる可能性があります。常に発生するとは限らず、さまざまなトリガーに基づいてさまざまな時期に発生するようです。アプリ起動直後の方が多いようです。例外をヒットせずに数分間使用できる場合、そのアプリケーション インスタンス中にヒットすることはおそらくないでしょう。

Connect のバグ レポートと同様{DynamicResource key}SolidColorBrushResourceDictionary. 一部の辞書は手動でロードされます (テーマのサポートのため)。これらの辞書のすべてを手動でフリーズしようとしましたが、効果がないようです。

UserControls にバインドされた ItemsControls を含むいくつかの s をメイン ウィンドウに追加すると、最近、例外が頻繁に発生するようになりましたObservableCollection。以前は、例外は 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 引数) で
       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、ブール式 styleLookup、EffectiveValueEntry& エントリ、ValueLookupType& sourceType、FrameworkElementFactory templateRoot) で
       System.Windows.StyleHelper.GetChildValue (UncommonField`1 dataField、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、ブール値 coerceWithDeferredReference、ブール値 coerceWithCurrentValue、OperationType operationType) で
       System.Windows.DependencyObject.InvalidateProperty (DependencyProperty dp) で
       System.Windows.StyleHelper.InvalidateResourceDependentsForChild (DependencyObject コンテナー、DependencyObject 子、Int32 childIndex、ResourcesChangeInfo 情報、FrameworkTemplate 親テンプレート) で
       System.Windows.TreeWalkHelper.InvalidateStyleAndReferences (DependencyObject d、ResourcesChangeInfo 情報、ブール値の containsTypeOfKey) で
       System.Windows.TreeWalkHelper.OnResourcesChanged (DependencyObject d、ResourcesChangeInfo 情報、Boolean raiseResourceChangedEvent) で
       System.Windows.FrameworkElement.OnAncestorChangedInternal (TreeChangeInfo 親ツリー状態) で
       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、ブール値 hasLogicalChildren) で
       System.Windows.DescendentsWalker`1.IterateChildren (DependencyObject d) で
       System.Windows.DescendentsWalker`1.StartWalk (DependencyObject startNode、ブール値の skipStartNode) で
       MS.Internal.PrePostDescendentsWalker`1.StartWalk (DependencyObject startNode、ブール値の 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 args) で
       System.Windows.Controls.Panel.OnItemsChanged (オブジェクトの送信者、ItemsChangedEventArgs args) で
       System.Windows.Controls.ItemContainerGenerator.OnRefresh() で
       System.Windows.Controls.ItemContainerGenerator.OnCollectionChanged (オブジェクトの送信者、NotifyCollectionChangedEventArgs args) で
       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 args) で
       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 args) で
       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 args) で
       System.Windows.DependencyObject.UpdateEffectiveValue (EntryIndex entryIndex、DependencyProperty dp、PropertyMetadata メタデータ、EffectiveValueEntry oldEntry、EffectiveValueEntry& newEntry、ブール値 coerceWithDeferredReference、ブール値 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 (ブール値の dependencySourcesChanged、ブール値の initialValue、ブール値の isASubPropertyChange) で
       MS.Internal.Data.PropertyPathWorker.UpdateSourceValueState (Int32 k、ICollectionView collectionView、オブジェクト 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 引数) で
       at ***.ViewModelBase.OnPropertyChanged(String name) in c:\***\ViewModelBase.cs:line 17
    .....

InvalidOperationException編集: また、ViewModel 基本クラスの PropertyChanged イベント内でスローされた s を単純に抑制しようとしました。ObservableCollectionこれにより、例外の数がいくらか減ったように見えましたが、今はのCollectionChangedイベントでヒットするだけです。

4

3 に答える 3

21

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

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

次のように変更する必要があります。

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

詳細な手順については、こちらを参照してください: Freezable から派生した WPF オブジェクトを XAML で凍結するにはどうすればよいですか? .

于 2011-09-06T18:23:29.313 に答える
3

これに対する回避策はないと思います。私が読んだことから、これを自分で処理する必要があるため、WPF は作成時にリソースを自動凍結します。そのため、そのリソースで DynamicResource を使用しようとするたびに、フリーズ可能な例外が発生します。

何が起こっているかについての Microsoft Foundation チームからの引用を次に示します。

「WPF は、スタイルまたはテンプレート内のすべてのフリーズ可能オブジェクトをフリーズします。スタイルとテンプレートは複数のスレッドで使用できますが、フリーズ可能オブジェクトはフリーズしない限り使用できません。現在、これを Application.Resources 内に配置されたものに拡張することを検討しています。同じスレッドの問題があります...凍結されたfreezableのDynamicResourceは機能しません.凍結されたfreezableには複数の親がある可能性があるためです-そのため、どの親がリソースを検索するかがあいまいです。

于 2011-08-22T15:27:41.123 に答える
0

ItemsControl と派生コントロールを使用した MVVM に関するバグのある動作になるたびに、まず VirtualizingStackPanel を無効にします。

<ItemsControl VirtualizingStackPanel.IsVirtualizing="False" />

ちょっと試して...

于 2011-08-22T14:34:41.393 に答える