Click here to Skip to main content
15,896,606 members
Articles / Desktop Programming / WPF

Multiple Window Interface for WPF

Rate me:
Please Sign up or sign in to vote.
4.88/5 (51 votes)
18 Jan 2008CPOL12 min read 376K   19.8K   134  
An article on the creation of multiple attachable/detachable windows inside of a WPF control.
<UserControl x:Class="WPFMwiWindows.Controls.MwiChild"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WPFMwiWindows"
    xmlns:controls="clr-namespace:WPFMwiWindows.Controls" >
  <UserControl.Resources>
    <controls:SolidBrushToColorConverter x:Key="SolidBrushToColorConverter" />
    <Path x:Key="PathPin" Width="10" Height="14" Data="M0,10 L 2,10 2,2 7,2 8,2 8,10 7,10 7,3 8,3 8,10 10,10 2,10 5,10 5,14" StrokeThickness="1.4" Stroke="White" />
    <Style TargetType="{x:Type Button}" >
      <Setter Property="Width" Value="22" />
      <Setter Property="Height" Value="22" />
      <Setter Property="Foreground" Value="White" />
      <Setter Property="Template" >
        <Setter.Value>
          <ControlTemplate TargetType="{x:Type Button}">
            <Border x:Name="ButtonBackground" 
                    BorderBrush="#FFF1F1F1"
                    BorderThickness="1"
                    CornerRadius="1,1,1,1" 
                    Margin="1,1,1,1"
                    >
              <Border.Background>
                <LinearGradientBrush EndPoint="0.494,0.889" StartPoint="0.494,0.028">
                  <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background, Converter={StaticResource SolidBrushToColorConverter}, ConverterParameter=150}" Offset="0.1" />
                  <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background, Converter={StaticResource SolidBrushToColorConverter}}" Offset="0.6" />
                </LinearGradientBrush>
              </Border.Background>
              <Grid>
                <AdornerDecorator>
                  <ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" />
                </AdornerDecorator>
              </Grid>
            </Border>
            <ControlTemplate.Triggers>
              <MultiTrigger>
                <MultiTrigger.Conditions>
                  <Condition Property="IsMouseOver" Value="False" />
                  <Condition Property="local:Controls.MwiChild.IsActive" Value="False" />
                </MultiTrigger.Conditions>
                <Setter Property="BorderBrush" TargetName="ButtonBackground" Value="DarkGray" />
                <Setter Property="Background" TargetName="ButtonBackground" >
                  <Setter.Value>
                    <LinearGradientBrush EndPoint="0.494,0.889" StartPoint="0.494,0.028">
                      <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background, Converter={StaticResource SolidBrushToColorConverter}, ConverterParameter=75}" Offset="0.1" />
                      <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background, Converter={StaticResource SolidBrushToColorConverter}}" Offset="0.6" />
                    </LinearGradientBrush>
                  </Setter.Value>
                </Setter>
              </MultiTrigger>
              <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Background" TargetName="ButtonBackground">
                  <Setter.Value>
                    <LinearGradientBrush EndPoint="0.494,0.889" StartPoint="0.494,0.028" >
                      <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background, Converter={StaticResource SolidBrushToColorConverter}, ConverterParameter=225}" Offset="0.1" />
                      <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background, Converter={StaticResource SolidBrushToColorConverter}}" Offset="0.6" />
                    </LinearGradientBrush>
                  </Setter.Value>
                </Setter>
              </Trigger>
            </ControlTemplate.Triggers>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
    <Style x:Key="MyDockPanelStyle" TargetType="DockPanel" >
      <Setter Property="Background" >
        <Setter.Value>
          <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
            <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush, Converter={StaticResource SolidBrushToColorConverter}}" Offset="0" />
            <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush, Converter={StaticResource SolidBrushToColorConverter}, ConverterParameter=100}" Offset="0.01" />
            <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush, Converter={StaticResource SolidBrushToColorConverter}}" Offset="0.1" />
            <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush, Converter={StaticResource SolidBrushToColorConverter}}" Offset="0.4" />
            <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush, Converter={StaticResource SolidBrushToColorConverter}, ConverterParameter=75}" Offset="0.9" />
            <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush, Converter={StaticResource SolidBrushToColorConverter}}" Offset="1.0" />
          </LinearGradientBrush>
        </Setter.Value>
      </Setter>
      <Style.Triggers>
        <MultiTrigger>
          <MultiTrigger.Conditions>
            <Condition Property="local:Controls.MwiChild.IsActive" Value="False" />
            <Condition Property="local:Controls.MwiChild.Minimized" Value="False" />
          </MultiTrigger.Conditions>
            <Setter Property="Background" >
              <Setter.Value>
                <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                  <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush, Converter={StaticResource SolidBrushToColorConverter}, ConverterParameter=60}" Offset="0" />
                  <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush, Converter={StaticResource SolidBrushToColorConverter}, ConverterParameter=130}" Offset="0.01" />
                  <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush, Converter={StaticResource SolidBrushToColorConverter}, ConverterParameter=60}" Offset="0.1" />
                  <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush, Converter={StaticResource SolidBrushToColorConverter}, ConverterParameter=60}" Offset="0.4" />
                  <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush, Converter={StaticResource SolidBrushToColorConverter}, ConverterParameter=105}" Offset="0.9" />
                  <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush, Converter={StaticResource SolidBrushToColorConverter}, ConverterParameter=60}" Offset="1.0" />
                </LinearGradientBrush>
              </Setter.Value>
            </Setter>
        </MultiTrigger>
        <MultiTrigger>
          <MultiTrigger.Conditions>
            <Condition Property="local:Controls.MwiChild.Minimized" Value="True" />
            <Condition Property="IsMouseOver" Value="True" />
          </MultiTrigger.Conditions>
          <Setter Property="Background" >
            <Setter.Value>
              <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush, Converter={StaticResource SolidBrushToColorConverter}, ConverterParameter=60}" Offset="0" />
                <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush, Converter={StaticResource SolidBrushToColorConverter}, ConverterParameter=130}" Offset="0.01" />
                <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush, Converter={StaticResource SolidBrushToColorConverter}, ConverterParameter=60}" Offset="0.1" />
                <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush, Converter={StaticResource SolidBrushToColorConverter}, ConverterParameter=60}" Offset="0.4" />
                <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush, Converter={StaticResource SolidBrushToColorConverter}, ConverterParameter=105}" Offset="0.9" />
                <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush, Converter={StaticResource SolidBrushToColorConverter}, ConverterParameter=60}" Offset="1.0" />
              </LinearGradientBrush>
            </Setter.Value>
          </Setter>
        </MultiTrigger>
      </Style.Triggers>
    </Style>
    <ItemsPanelTemplate x:Key="ButtonItemsPanel" >
      <StackPanel x:Name="MyStackPanel3" Orientation="Horizontal" HorizontalAlignment="Right" />
    </ItemsPanelTemplate>
    <Style TargetType="{x:Type local:Controls.MwiChild}" >
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="{x:Type local:Controls.MwiChild}">
            <Border x:Name="MwiBorder"
                    Background="{TemplateBinding Background}"  
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="3,1,3,3" 
                    CornerRadius="2,2,2,2"                     
              >
              <AdornerDecorator>
                <DockPanel x:Name="DockPanelWindow" >
                  <DockPanel x:Name="PanelTitle" DockPanel.Dock="Top" Style="{StaticResource MyDockPanelStyle}" MinHeight="{Binding Path=MinSize.Height}" 
                             local:Controls.MwiChild.IsDraggable="true" local:Controls.MwiChild.IsActive="{TemplateBinding IsSelected}"
                             local:Controls.MwiChild.Minimized="{TemplateBinding IsMinimized}" >
                    <StackPanel x:Name="PanelButtons" Orientation="Horizontal" DockPanel.Dock="Right" HorizontalAlignment="Right" Visibility="{TemplateBinding PanelButtonsVisiblity}" >
                      <ItemsControl x:Name="MyItemsControl1" ItemsSource="{Binding TitleBarButtons}" ItemsPanel="{StaticResource ButtonItemsPanel}" />
                      <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
                        <Button x:Name="detachButton" Command="local:Controls.MwiChild.DetachWindow" local:Controls.MwiChild.IsActive="{TemplateBinding IsSelected}" Background="{TemplateBinding BorderBrush}"  >
                          <Path x:Name="PathPin" Width="10" Height="14" Data="M0,10 L 2,10 2,2 7,2 8,2 8,10 7,10 7,3 8,3 8,10 10,10 2,10 5,10 5,14" StrokeThickness="1.4" Stroke="White" />
                        </Button>
                        <Button x:Name="minButton" Click="minButton_Click" local:Controls.MwiChild.IsActive="{TemplateBinding IsSelected}" Background="{TemplateBinding BorderBrush}" >
                          <Path Data="M-4,12 L2,12 2,11 -4,11" StrokeThickness="2.0" Fill="White" Stroke="White" />
                        </Button>
                        <Button x:Name="maxButton" Click="maxButton_Click" local:Controls.MwiChild.IsActive="{TemplateBinding IsSelected}" Background="{TemplateBinding BorderBrush}" >
                          <Path StrokeThickness="1.0" Stroke="White" >
                            <Path.Style>
                              <Style TargetType="Path" >
                                <Setter Property="Data" Value="M0,2 L10,2 10,3 0,3 0,4 10,4 10,12 0,12 0,2" />
                                <Style.Triggers>
                                  <DataTrigger Binding="{Binding IsMaximized}" Value="True" >
                                    <Setter Property="Data" Value="M0,5 L7,5 7,6 0,6 0,7 7,7 7,12 0,12 0,5 2,5 2,1 9,1 9,2 2,2 2,3 9,3 9,8 7,8" />
                                  </DataTrigger>
                                </Style.Triggers>
                              </Style>
                            </Path.Style>
                          </Path>
                        </Button>
                        <Button x:Name="closeButton" Click="closeButton_Click" local:Controls.MwiChild.IsActive="{TemplateBinding IsSelected}" Background="Red" >
                          <Path Data="M1,1 L11,11 M11,1 L1,11" StrokeThickness="2.0" Stroke="White" />
                        </Button>
                      </StackPanel>
                    </StackPanel>
                    <Grid x:Name="PanelTitleIcon" DockPanel.Dock="Left" local:Controls.MwiChild.IsDraggable="true" >
                      <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="*" />
                      </Grid.ColumnDefinitions>
                      <!--StackPanel x:Name="PanelTitleIcon" Orientation="Horizontal" DockPanel.Dock="Left" local:Controls.MwiChild.IsDraggable="true" -->
                      <Image x:Name="ImageIcon" Source="{Binding Icon}" Width="16" Height="16" Grid.Column="0" Stretch="Uniform" local:Controls.MwiChild.IsDraggable="true" Margin="1,0,1,0" />
                      <TextBlock x:Name="TextBlockTitle" Text="{Binding Title}" Foreground="White" Grid.Column="1" 
                                 TextWrapping="NoWrap"  TextTrimming="CharacterEllipsis" HorizontalAlignment="Left"   
                                 VerticalAlignment="Center" local:Controls.MwiChild.IsDraggable="true" />
                      <!--/StackPanel-->
                    </Grid>
                  </DockPanel>
                  <AdornerDecorator>
                    <ContentPresenter DockPanel.Dock="Top" />
                  </AdornerDecorator>
                </DockPanel>
              </AdornerDecorator>
            </Border>
            <ControlTemplate.Triggers>
              <Trigger Property="IsSelected" Value="False" >
                <Setter Property="BorderBrush" TargetName="MwiBorder" >
                  <Setter.Value>
                    <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                      <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush, Converter={StaticResource SolidBrushToColorConverter}, ConverterParameter=75}" Offset="0" />
                    </LinearGradientBrush>
                  </Setter.Value>
                </Setter>                
              </Trigger>
              <MultiTrigger>
                <MultiTrigger.Conditions>
                  <Condition SourceName="PanelTitle" Property="local:Controls.MwiChild.Minimized" Value="True" />
                  <Condition SourceName="PanelTitle" Property="IsMouseOver" Value="True" />
                </MultiTrigger.Conditions>
                <Setter Property="BorderBrush" TargetName="MwiBorder" >
                  <Setter.Value>
                    <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                      <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush, Converter={StaticResource SolidBrushToColorConverter}, ConverterParameter=75}" Offset="0" />
                    </LinearGradientBrush>
                  </Setter.Value>
                </Setter>
              </MultiTrigger>
              <MultiTrigger>
                <MultiTrigger.Conditions>
                  <Condition SourceName="PanelTitle" Property="local:Controls.MwiChild.Minimized" Value="True" />
                  <Condition SourceName="PanelTitle" Property="IsMouseOver" Value="False" />
                </MultiTrigger.Conditions>
                <Setter Property="BorderBrush" TargetName="MwiBorder" >
                  <Setter.Value>
                    <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                      <GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush, Converter={StaticResource SolidBrushToColorConverter}}" Offset="0" />
                    </LinearGradientBrush>
                  </Setter.Value>
                </Setter>
              </MultiTrigger>
            </ControlTemplate.Triggers>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
      <Style.Triggers>        
        <DataTrigger Binding="{Binding IsWindowed}" Value="True" >
          <Setter Property="Template" >
            <Setter.Value>
              <ControlTemplate TargetType="{x:Type local:Controls.MwiChild}">
                <DockPanel>
                  <ContentPresenter DockPanel.Dock="Top" />
                </DockPanel>
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </DataTrigger>
        <DataTrigger Binding="{Binding IsMinimized}" Value="True" >
          <Setter Property="LayoutTransform" >
            <Setter.Value>
                <ScaleTransform ScaleX="1" ScaleY="-1" />              
            </Setter.Value>
          </Setter>
          <Setter Property="Margin" Value="1,1,0,0" />                          
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </UserControl.Resources>
  <!--Grid x:Name="MyGrid1" Background="Blue" >
    <TextBox x:Name="MyTextBlock2" Text="{Binding DisplayTitle}" Width="100" Background="Yellow" Height="24" IsEnabled="True" />
  </Grid-->
</UserControl>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Unknown
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions