WPF中的许多类型都源于Freezable
.它为可变POCO对象提供了不变性,并且显然可以在某些情况下提高性能.
有没有人发现在他们的WPF应用程序中冻结对象大大提高了性能?如果是这样,那么哪些项目在冻结时会产生最大的性能差异?
(请注意,我也发布了类似但不同的问题)
我有一个WPF DataGrid ..
我想冻结WPF DataGrid的第一列,同时水平scrlling ..
我的代码是:
<DataGrid Name="dgQuestionTemplate" HorizontalAlignment="Left" Grid.Row="1" Width="870" HorizontalScrollBarVisibility="Auto" IsReadOnly="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding ExamDate}" Header="Date" IsReadOnly="True" Width="90" />
<DataGridTextColumn Binding="{Binding ExamName}" Header="Test Name" IsReadOnly="True" Width="195" />
<DataGridTextColumn Binding="{Binding Batch}" Header="Batch" IsReadOnly="True" Width="100" />
<DataGridTextColumn Binding="{Binding ExamTime}" Header=" Count Down [Days: hr: min: sec]" IsReadOnly="True" Width="*" />
</DataGrid.Columns>
</DataGrid>
Run Code Online (Sandbox Code Playgroud) 我最近遇到了一个非常糟糕的WPF错误.我认为它与Microsoft Connect上的这个错误相同.
我们的应用程序使用Visual Studio 2010定位.NET 4.0 Client Profile.
基本上,当ViewModel触发对任何导致项目在ItemsControl中移动的属性或集合的更改时,可能会抛出下面的异常.它并不总是发生,似乎是基于不同时间的不同触发器而发生的.在启动应用程序后不久,它似乎更有可能.如果您可以使用它几分钟而不会遇到异常,那么您可能永远不会在该应用程序实例期间遇到它.
就像Connect错误报告一样,我正在使用来自a的{DynamicResource key}
加载SolidColorBrush
es ResourceDictionary
.一些字典是手动加载的(用于支持).我尝试手动冻结这些词典中的所有内容,但似乎没有帮助.
最近,当我向UserControl
主窗口添加了几个s并将其中的ItemsControls绑定到ObservableCollection
s 时,异常变得更加频繁.以前,我只看到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& …
我正在使用MVVM模式编写应用程序.我通过将我的视图的DataContext属性设置为我的ViewModel的实例来向我的视图提供数据.一般来说,我只是从那里使用Binding并继续我的方式.
最近,我试图在我的ViewModel提供的"选择项目"的集合之外实现一个带有"额外"元素的ComboBox.
<ComboBox>
<ComboBox.ItemsSource>
<CompositeCollection>
<ComboBoxItem IsEnabled="False">Select Item</ComboBoxItem>
<CollectionContainer Collection="{Binding MyItemsCollection}" />
</CompositeCollection>
</ComboBox.ItemsSource>
</ComboBox>
Run Code Online (Sandbox Code Playgroud)
问题是,CompositeCollection不是Freezable:Freezable Objects Overview.这会导致仅显示静态ComboBoxItem,而不会导致我的绑定表达式产生任何结果.
我对这个问题的第一反应是,只是实现自己CompositeCollection的版本是可冻结.但是,这引出了以下问题:
为什么CompositeCollection首先不是Freezable?
我担心的是,通常这些决定是出于某种原因而做出的,我不觉得我对Freezable的了解不足以说明为什么他们没有从中继承.我知道我可以实现这个系列,但我担心如果我这样做会有一个可衡量的性能差异.
任何帮助,将不胜感激.谢谢!
另外:请注意,我意识到我可以插入Null或其他一些特殊值,并提供模板或valueconverter来做我想要的.这不是我感兴趣的问题......只是上面的粗体问题.
更新:
经过ArsenMkrt的评论进行了一些进一步的研究后,我发现我认为这实际上是一种疏忽.证据如下:
FreezableCollection<T>
.我没有生成CollectionViews,这使得它不能直接满足我的需求.我目前解决这个问题的计划是创建一个具有CompositeCollection和属性的新集合FreezableCollection<T>
.我不知道它是否还能正常工作,但我正在考虑这样的事情:
public class BindableCompositeCollection : FreezableCollection<object>, ICollectionViewFactory
Run Code Online (Sandbox Code Playgroud)
如果有人有更好的选择,我想听听!
我收到这个错误:
不能使用属于与其父Freezable不同的线程的DependencyObject
那有什么意思?是英文的吗?父母被冻结了,还是只是可以冻结?任何使父母不可冻结的方法,如果它让错误消失了?
发生了什么:
我在WPF应用程序中有两个opengl winforms控件,到目前为止,一切都在顺利进行(我认为).现在,我添加了一个更新,以便当一个winform控件更新图像时,另一个也应该.这实际上曾经工作过,现在我收到了这个错误.逐步执行代码会导致崩溃发生在随机位置,这使我相信它是一个垃圾收集错误(即,另一个线程中的某些更新正在创建收集垃圾的东西,并且该收集在随机时间发生).
异常是在主run方法中捕获的,它是一个InvalidOperationException.
我在这里抓住稻草.我从哪里开始?
编辑:看起来引起问题的电话是这样的:
if (imagePanel.InvokeRequired)
{
imagePanel.Invoke(new System.Windows.Forms.MethodInvoker(delegate{
imagePanel.ClearImages();
}));
}
else
{
imagePanel.ClearImages();
}
Run Code Online (Sandbox Code Playgroud)
我还在跟踪它; 如果该系列行被注释掉,崩溃仍然发生,并且线程状态具有"刚刚结束"的线程(因此垃圾收集假设).
有时我的应用程序中出现以下错误:
无法使用与其父级Freezable属于不同线程的DependencyObject
我知道如何解决这种错误,但是在那种情况下,我不知道它在哪里发生,所以我不知道要解决什么...异常的堆栈跟踪仅包含.NET Framework代码,而不包含我的代码(除了Main方法):
at System.Windows.Freezable.EnsureConsistentDispatchers(DependencyObject owner, DependencyObject child)
at System.Windows.Freezable.OnFreezablePropertyChanged(DependencyObject oldValue, DependencyObject newValue, DependencyProperty property)
at System.Windows.Freezable.OnFreezablePropertyChanged(DependencyObject oldValue, DependencyObject newValue)
at System.Windows.Media.RenderData.PropagateChangedHandler(EventHandler handler, Boolean adding)
at System.Windows.UIElement.RenderClose(IDrawingContent newContent)
at System.Windows.Media.VisualDrawingContext.CloseCore(RenderData renderData)
at System.Windows.Media.RenderDataDrawingContext.DisposeCore()
at System.Windows.Media.DrawingContext.System.IDisposable.Dispose()
at System.Windows.Media.RenderDataDrawingContext.Close()
at System.Windows.UIElement.Arrange(Rect finalRect)
at MS.Internal.Helper.ArrangeElementWithSingleChild(UIElement element, Size arrangeSize)
at System.Windows.Controls.ContentPresenter.ArrangeOverride(Size arrangeSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.WrapPanel.arrangeLine(Double v, Double lineV, Int32 start, Int32 end, Boolean useItemU, Double itemU)
at System.Windows.Controls.WrapPanel.ArrangeOverride(Size finalSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at …
Run Code Online (Sandbox Code Playgroud) 我已经尝试过MSDN但是没有从Freezable派生的例子.
更新:
在MSDN中是的,有一个动画示例,但它太复杂了.需要更简单的东西来理解freezable.
在我的场景中,我想在我想在后台任务中渲染它之前冻结一个不变的BitmapCacheBrush.不幸的是我收到错误"这个Freezable不能被冻结".是否有任何解决方法或hacky方式冻结也不是freezable对象?也许可以通过反射设置正确的属性来达到这个目标?提前谢谢你们.
编辑:(我的示例代码请求)
public static class ext
{
public static async Task<BitmapSource> RenderAsync(this Visual visual)
{
var bounds = VisualTreeHelper.GetDescendantBounds(visual);
var bitmapCacheBrush = new BitmapCacheBrush(visual);
bitmapCacheBrush.BitmapCache = new BitmapCache();
// We need to disconnect the visual here to make the freezable freezable :). Of course this will make our rendering blank
//bitmapCacheBrush.Target = null;
bitmapCacheBrush.Freeze();
var bitmapSource = await Task.Run(() =>
{
var renderBitmap = new RenderTargetBitmap((int)bounds.Width,
(int)bounds.Height, 96, 96, PixelFormats.Pbgra32);
var dVisual = new DrawingVisual();
using (DrawingContext context = dVisual.RenderOpen()) …
Run Code Online (Sandbox Code Playgroud)