0

I have a WPF application where a line shape is only displayed when the application window is resized, as shown here:

The red line is drawn on-the-fly, it is not defined in XAML. It displays fine.

The blue line is defined in XAML, but its dimensions are changed within the OnRender() call. If its dimensions are not changed, or if only some of its dimensions are changed, the blue line is displayed on startup. But when all the dimensions of the blue line are changed, it is not displayed on startup. It is only displayed on application resize.

Here's the XAML code:

<Window x:Class="canvas_line.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:canvas_line" 
        Title="MainWindow" Height="284" Width="228">
    <Canvas Name="canvas">
        <local:show_line />
        <Line Name="my_line" Stroke="Blue" 
            X1="50" Y1="40" X2="50" Y2="80" StrokeThickness="4" />
    </Canvas>
</Window>

And the C# code-behind file:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Linq;

namespace canvas_line
{
    public partial class show_line: FrameworkElement
    {
        protected override void OnRender(DrawingContext dc)
        {
            base.OnRender(dc);              // Good practice.

            // Draw a brand-new red line defined here only 
            // (not defined in XAML).

            Pen dp = new Pen(Brushes.Red, 4);
            dc.DrawLine(dp, new Point(100, 150), new Point(100, 200));

            // Now modify coordinates of the blue line defined in XAML.

            Canvas cp = (Canvas)this.Parent;
            var my_line = cp.Children.OfType<Line>().FirstOrDefault();
            my_line.X1 = 100;
            my_line.Y1 = 20;
            my_line.X2 = 100;
            my_line.Y2 = 50;

            // Problem: The blue line is not displayed unless
            // the application window is resized.
        }
    }
}

The zip file for the entire project is here (there is very little code in the project, I have pruned it to the absolute minimum necessary to demo the problem):

https://anonfiles.com/file/18c6edce296927b43ed0b0d595574a80

I have tried all sorts of combinations of calls to UpdateLayout() and InvalidateVisual(), to no effect. Why is this happening, and is there a workaround? My ultimate goal is to be able to animate the blue line so as to have it blink.

I am on Windows 7, Visual Studio 10, .NET 4.0 Client Profile.

Sabuncu
  • 5,095
  • 5
  • 55
  • 89
  • PS: I need to have the call to `OnRender()` because, although not shown here, I have to do low-level glyph drawing. Thanks. – Sabuncu Jun 26 '14 at 19:24
  • Have you tried changing the location prior to the base.OnRender? – John Koerner Jun 26 '14 at 19:27
  • @JohnKoerner Yes, does not work. – Sabuncu Jun 26 '14 at 19:30
  • I suspect you are clearing the drawing context in `base.OnRender()`. Would you be able to post that code? Alternatively, you could check to see if removing the `base.OnRender()` brings back the blue line. – Tyler Kendrick Jun 26 '14 at 19:45
  • @TylerKendrick I removed `base.OnRender()`, made no difference. – Sabuncu Jun 26 '14 at 19:47
  • My only other suggestion would be to attempt calling different `.Invalidate*()` methods on the `my_line` object. Because you are already in OnRender, it may not be updating correctly. – Tyler Kendrick Jun 26 '14 at 19:57
  • @TylerKendrick I tried your suggestion and called those methods after `InitializeComponent()` but it did not help. – Sabuncu Jun 26 '14 at 21:03

1 Answers1

2

if you put it like this it will draw properly

 <Canvas Name="canvas">
    <Line Name="my_line" Stroke="Blue" X1="50" Y1="40" X2="50" Y2="80" StrokeThickness="4" />
    <local:show_line />
 </Canvas>  
Heena
  • 8,450
  • 1
  • 22
  • 40