Michael Repucci
Michael Repucci

Reputation: 1663

Can I duplicate a XAML/WPF window into a second window, like a picture-in-picture TV?

I've got an application with two XAML/WPF windows (derived from NavigationWindow), each window contains one parent UserControl, in which all child controls are placed. In one of the windows, I'd like to show the second window's content (really just the parent UserControl), in the manner like a picture-in-picture TV. In this way the user could view the first window, and see what is happening in the second window at the same time. Note, that I do not want two independent copies of this second window's UserControl (that would be easy), but to mirror the content of the second window in the first window.

This is vaguely similar to the Windows 7 Taskbar thumbnail previews, so I figure that it must be doable. Ideally, however, I'd also like to be able to interact with that window-in-a-window, in the same way as I would if I were to pull up the original window.

This is similar to this question, except that I'd like just a single window from the same application to be copied, instead of the whole desktop. Also similar to this question, but I need a bit more hand-holding, as I'm not super-familiar with C#/WPF. Some code snippets would be great.

Thank you in advance!

Upvotes: 6

Views: 3909

Answers (2)

erodewald
erodewald

Reputation: 1825

Use a visual brush. It will not be interactive, but that seems to suit your needs.

Paste this code into Kaxaml to see it in action.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Page.Triggers>
        <EventTrigger RoutedEvent="Page.Loaded">
            <EventTrigger.Actions>
                <BeginStoryboard>
                    <Storyboard Storyboard.TargetName="sampleAnimation" Storyboard.TargetProperty="(FrameworkElement.RenderTransform).(RotateTransform.Angle)">
                        <DoubleAnimation Duration="00:00:10" RepeatBehavior="Forever" To="-360">
                            <DoubleAnimation.EasingFunction>
                                <ElasticEase/>
                            </DoubleAnimation.EasingFunction>
                        </DoubleAnimation>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger.Actions>
        </EventTrigger>
    </Page.Triggers>
    <Page.Resources>
        <VisualBrush x:Key="contentBrush" Stretch="None" Visual="{Binding ElementName=content}"/>
    </Page.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <TextBlock FontSize="25" Text="Content to mirror:"/>
        <Grid
            x:Name="content"
            Grid.Row="1"
            Margin="5"
            Background="#11000000"
            ClipToBounds="True">
            <TextBox
                x:Name="sampleAnimation"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                FontSize="60"
                FontWeight="Light"
                Foreground="Red"
                RenderTransformOrigin="0.5,0.5"
                Text="Hello!">
                <TextBox.RenderTransform>
                    <RotateTransform Angle="0"/>
                </TextBox.RenderTransform>
            </TextBox>
        </Grid>
        <TextBlock Grid.Row="2" FontSize="25" Text="Mirrored content using VisualBrush:"/>
        <Grid Grid.Row="3" Background="{StaticResource contentBrush}">
        </Grid>
    </Grid>
</Page>

Upvotes: 3

Lee Louviere
Lee Louviere

Reputation: 5262

Use a visual brush as a fill on a rectangle.

You won't be able to interact with it though... but this is how preview thumbnails on the taskbar are accomplished.

<Grid HorizontalAlignment="Left" Name="A" Height="100" Width="100">
    <Grid.Background>
        <SolidColorBrush Opacity="0" Color="White"/>
    </Grid.Background>
    <!-- Contents -->
</Grid>


<Rectangle Name="RA" VerticalAlignment="Top" Width="100" Height="100" HorizontalAlignment="Left" Stroke="Black">
    <Rectangle.Fill>
        <!-- Creates the reflection. -->
        <VisualBrush  AutoLayoutContent="True"  Visual="{Binding ElementName=A}" ViewboxUnits="RelativeToBoundingBox" ViewportUnits="RelativeToBoundingBox" Stretch="Fill" AlignmentX="Left" AlignmentY="Top" Viewport="0,0,1,1" Viewbox="0,0,1,1" TileMode="None">
        </VisualBrush>
    </Rectangle.Fill>
</Rectangle>

To interact, you'd have to bind all the properties to an identical screen, and use a layout transform to shrink it.

<StackPanel>
    <Grid>
        <TextBox Name="A"/>
    </Grid>
    <Grid>
        <Grid.LayoutTransform>
            <ScaleTransform CenterX=".5" CenterY=".5"  ScaleX=".25" ScaleY=".25"/>
        </Grid.LayoutTransform>
        <TextBox Name="B" Text="{Binding ElementName=A, Path=Text, UpdateSourceTrigger=PropertyChanged}"/>
    </Grid>
</StackPanel>

Upvotes: 0

Related Questions