Hi,
I've found a perfect storm of conditions that create a situation where my panel is no longer updating properly.
Here is the concept: I have a grid with a viewbox displaying a canvas with lines in radiating patterns. When I attempt to render the entire grid to bitmap, the bitmap looks fine. However, at this point forward, if I change my data source which my lines are bound to, the entire group of lines disappear from the panel.
Here is what I have found: This only happens with the following three conditions in place.
- VisualBox displaying a canvas with the lines (if I just display a canvas with the lines, regardless of the other two conditions, it behaves properly).
- I have a solution demonstrating the issue in .Net 3.5.1 and in .Net 4... the issue only happens in .Net 4 (even with the other two items in place).
- This only happens after calling RenderTargetBitmap Render().
Thanks for the help! -James
Here is the main display:
<Window x:Class="LobCanvas.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:LobCanvas"
Title="Window1" Height="850" Width="800">
<Window.DataContext>
<local:ViewModel x:Name="viewModel"/>
</Window.DataContext>
<Window.Resources>
<local:AngleToCoordinateConverter x:Key="angleToCoordinateConverter"/>
</Window.Resources>
<Grid x:Name="mainGrid" Height="800" Width="800">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Rectangle Width="700" Height="700">
<Rectangle.Fill>
<VisualBrush Viewbox="100,0,700,700" ViewboxUnits="Absolute"
Viewport="0,0,1,1" ViewportUnits="RelativeToBoundingBox" x:Name="visualBrush">
<VisualBrush.Visual>
<Canvas Background="AntiqueWhite" Width="900" Height="900">
<ItemsControl ItemsSource="{Binding Origins}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding Sprays}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Line Stroke="Red"
X1="0" Y1="0"
StrokeThickness="2">
<Line.X2>
<MultiBinding Converter="{StaticResource angleToCoordinateConverter}" ConverterParameter="X">
<Binding Path="Angle"/>
<Binding Path="X1">
<Binding.RelativeSource>
<RelativeSource Mode="Self"/>
</Binding.RelativeSource>
</Binding>
</MultiBinding>
</Line.X2>
<Line.Y2>
<MultiBinding Converter="{StaticResource angleToCoordinateConverter}" ConverterParameter="Y">
<Binding Path="Angle"/>
<Binding Path="Y1">
<Binding.RelativeSource>
<RelativeSource Mode="Self"/>
</Binding.RelativeSource>
</Binding>
</MultiBinding>
</Line.Y2>
</Line>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Left" Value="{Binding X}"/>
<Setter Property="Canvas.Top" Value="{Binding Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</Canvas>
</VisualBrush.Visual>
</VisualBrush>
</Rectangle.Fill>
</Rectangle>
<StackPanel Grid.Row="1" Width="100">
<Button Content="Snapshot!" Click="TakeSnapshot"/>
<Button Content="Manipulate!" Click="ManipulateData"/>
</StackPanel>
</Grid>
Here is the code behind, particular the button to take a snap shot, and the button to manipulate my data source. Again, if you take the snapshot, then manipulate, the bitmap looks fine but the panel is no longer displaying lines properly:
private void TakeSnapshot(object sender, RoutedEventArgs e)
{
Window1.CaptureScreen(mainGrid, 96, 96);
}
private void ManipulateData(object sender, RoutedEventArgs e)
{
Random rand = new Random();
viewModel.Origins[0].Sprays.Add(new LineSpray(rand.NextDouble() * 360));
}
private static BitmapSource CaptureScreen(Panel target, double dpiX, double dpiY)
{
if (target == null)
{
return null;
}
// Measure and arrange the container
target.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
target.Arrange(new Rect(target.DesiredSize));
Rect bounds = VisualTreeHelper.GetDescendantBounds(target);
RenderTargetBitmap rtb = new RenderTargetBitmap((int)(bounds.Width * dpiX / 96.0),
(int)(bounds.Height * dpiY / 96.0),
dpiX,
dpiY,
PixelFormats.Pbgra32);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext ctx = dv.RenderOpen())
{
VisualBrush vb = new VisualBrush(target);
ctx.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size));
}
rtb.Render(dv);
return rtb;
}
I can post the view model or the converter if requested, but at that point, it may be easier for me to email my entire solution.