1

Having a main window and a canvas class Graphcontext where animations and several shapes interact like:

xaml

<DockPanel Name="stackPanel2" DockPanel.Dock="Left" Margin="10,10,10,10" LastChildFill="True" >
      <myctrl:Graphcontext x:Name="graphSurface" Background="Black" >
      </myctrl:Graphcontext>
</DockPanel>

code

public class Graphcontext : Canvas
    {

        Ellipse _fixedCircle;
        internal int CavasWidth { get; set; }
        internal int CavasHeight { get; set; }

        public void drawSinglePoint(SolidColorBrush color)
        {
            this.Children.Clear();
            _fixedCircle = new Ellipse();
            _fixedCircle.Width = 25;
            _fixedCircle.Height = 25;
            _fixedCircle.Stroke = color;
            _fixedCircle.Fill = color;
            _fixedCircle.StrokeThickness = 3;
            // Get the center x and y coordinates
            double x = this.ActualWidth / 2 ;
            double y = this.ActualHeight / 2 ;
            _fixedCircle.Margin = new Thickness(x, y, 1, 1);
            // Add the circle to the canvas
            this.Children.Add(_fixedCircle);
            this.InvalidateVisual();
        }
   ...
}

I want to clon GraphContext inside other maximized canvas in second other monitor maybe using Viewbox.

I have tried

Canvas copycanvas = XamlReader.Parse(XamlWriter.Save(graphSurface)) as Canvas;
Viewbox vb = new Viewbox() { StretchDirection = StretchDirection.Both, Stretch=Stretch.Uniform };
vb.Child = copycanvas;
Window newwin = new Window() { Content = vb };
newwin.Show();

However when graphSurface is updated the copycanvas is not updated. I actually see the point, but when I do for instance an animation using a storyboard from codebehind copycanvas is not updated.

What do I need to do so copycanvas is always a mirror of graphSurface ?

Do I need to copy all logic into other control?, So that way it always be the same, maybe a little delay...

Maybe databinding canvas to viewbox could do it, but how would it be?

Kaiido
  • 123,334
  • 13
  • 219
  • 285
edgarmtze
  • 24,683
  • 80
  • 235
  • 386
  • Did you consider rendering the canvas to a bitmap and simply show the bitmap? That way you could even pass the image over a simple network share and have your own remote desktop – Emond Apr 01 '15 at 16:05
  • You could change your `CopyCanvas` to a property which simply return `XamlReader.Parse(XamlWriter.Save(ORIGINALCANVAS)) as Canvas;`; data bind `CopyCanvas` to your `ViewBox`, and raise `propertyChanged("CopyCanvas")`, whenever the `OriginalCanvas` get updated. – Bolu Apr 01 '15 at 16:08
  • Would that idea work for animations and storyboards ocurring on ORIGINALCANVAS? – edgarmtze Apr 01 '15 at 16:16
  • @cMinor do you mean the idea with the Bitmap or the xml-parsing? – Koopakiller Apr 06 '15 at 16:10
  • @Koopakiller I mean XML Parsing. But I do not know if bitmap rendering would support several animations As I need high quality – edgarmtze Apr 06 '15 at 16:13
  • @cMinor I tried a little bit with rendering-mechanism and "screenshots", but the animation quality was really bad - I have no more ideas yet. – Koopakiller Apr 06 '15 at 18:33
  • I am trying to follow the ´XamlReader´ aproach but with no success... – edgarmtze Apr 06 '15 at 18:34

2 Answers2

1

You could use VisualBrush, Example1; Example2

So basically, you can just create a VisualBrush and data-bind your current GraphContext to its Visual property, which creates a duplicate image of the GraphContext.

Code in your main window:

MirrorWindow newwin = new MirrorWindow ();
newwin.DataContext = graphSurface;
newwin.Show();

XAML for your mirroring window:

 <Grid>
        <Grid.Background>
            <VisualBrush Stretch="Uniform" Visual="{Binding}"/>
        </Grid.Background>
 </Grid>

Sample:

MainWindow with a basic Canvas and animation on mousedown:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Canvas Background="Black" x:Name="graphSurface">
            <Canvas.Triggers>
                <EventTrigger RoutedEvent="MouseDown">
                    <BeginStoryboard>
                        <Storyboard>
                            <ColorAnimation  To="Red" Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)" FillBehavior="Stop" Duration="0:0:5"/>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Canvas.Triggers>
        </Canvas>
    </Grid>
</Window>

Mirroring window:

<Window x:Class="WpfApplication1.Mirror"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Mirror" Height="300" Width="300">
    <Grid>
        <Grid.Background>
            <VisualBrush Stretch="Fill" Visual="{Binding}"/>
        </Grid.Background>
    </Grid>
</Window>

MainWindow code behind:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        Mirror mm = new Mirror();
        mm.DataContext = this.graphSurface;
        mm.Show();
    }        
}

Result: Mouse click on the Mainwindow, both MainWindow and Mirror will show color change animation.

Community
  • 1
  • 1
Bolu
  • 8,696
  • 4
  • 38
  • 70
0

when you start code in wpf you should stop treating elements like past programming languages you have to use MVVM pattern to do things right this is done by setting the data-context for the window m-v-vm pattern have there things

view-model:

a class Implements INotifyPropertyChanged with some public properties witch raise event propertychanged when set and initialization sub witch add data like circle position , color,etc.

view :

the xaml witch data-bind to view model puplic properties with binding mods you can bind data in one->way (to target) , two<->way , one<-way to source

model :

your main window witch have initialization sub like InitializeComponent() ; this.DataContext = New view_model.mainsub

so in your example you should --> make some data in view-model class -->start new window --> set window Datacontext to the new view_model

let's say you want to get data from the view like list current item

you should bind the selected_index property to a one-way to source mode so that it will change the corresponding property witch bind to it in the view_model class

then you can check if the property is changed in the mainwindow (model) and that's who MVVM works

please Don't get elements from view you should get data in (view_model class)type from the view

and screen in wpf is for posting data only don't go throw child / parent relation in the end you will get stuck