2012-02-29 18 views
3

私は、ユーザーが次のような文書を管理することができますTabControlがあります。TabControlを拡張して、TabItemまたはドキュメントをドッキングして浮動させるにはどうすればよいですか?

enter image description here

いくつかの点では、私は、ユーザーがTabItem Sを浮遊し、TabControlに戻ってそれらをドッキングできるようにする機能を追加したいですVisual Studioでできることの多くに沿っています。この機能を使用すると、ユーザーはドキュメントの比較やコピー/貼り付けなどをより簡単に行うことができます。

私はこれを行う方法についていくつかの一般的なアイディアを持っています。 TabControlは、ItemsSourceがドキュメントビューモデルのリストにバインドされています。タブfloatに

  1. TabItemのタブストリップ領域にThumbコントロールを追加します。
  2. ユーザーがThumbをドラッグすると、関連付けられたドキュメントビューモデルがTabControlリストから削除されます。
  3. 個別の文書Windowが、その文書を表示/編集するために、文書ビューモデルにバインドされます。

タブをドッキングするには:

  1. はタブストリップ領域の上にドラッグする文書Windowを認識するTabControlDragOverイベントハンドラを追加します。
  2. 関連するドキュメントビューモデルがTabControlリストに追加されました。
  3. 文書Windowは閉じられています。

これを実行する方法の例はありますか、これを行う方法はありますか?

ありがとうございました。

+2

は[AvalonDock(http://avalondock.codeplex.com/)を見て –

+0

優秀、私はAvalonDockをチェックアウトします、ありがとう! –

+1

[AvalonDock](http://avalondock.codeplex.com/)をご覧ください。私はAvalonDockが別々のウィンドウを使用すると信じています。 MVVMを使用している場合は、各ViewModelに「DataTemplate」を定義する必要があると思います(つまり、WindowクラスでViewを定義することはできません)。 –

答えて

2

既存のコントロールが見つからない場合や、使用したくない場合は、dragging and dropping between databound controlsに関するBea Stollnitzの記事をお勧めします。 DockPanelを使用してデータバインドされたオブジェクトが使用するものを特定するには、おそらくそれを少し変更する必要がありますが、過去に変更しやすいコードを見つけました。あなたがそのようなTabControlDockPanel、そしてときのように、セットアップ2つのデータバインドされたコントロールは、ドラッグう

/あなたが実際に/ドラッグItemsSources間のデータバインドされたアイテムをドロップされる2つの間に落下。

+0

いいえ、感謝のレイチェル。そのサンプルでは、​​現在のWindowの制限を回避することを試みましたか?理想的には、私はドッキング解除されたドキュメントのための別々のウィンドウを持っていると思います。 –

+1

@DaveClemmerいいえ、複数のウィンドウで試したことはありませんが、別の 'UserControls 'の間でアイテムをドラッグアンドドロップするのに使っています。 – Rachel

+0

@DaveClemmer:AvalonDockは別々のウィンドウを使用していると思います。 MVVMを使用している場合は、各ViewModelに「DataTemplate」を定義する必要があると思います(つまり、WindowクラスでViewを定義することはできません)。 –

2

私はついにこの機能を実装しました。私はAvalonDock 2.0を使用しました。これはMVVMに優しいものです。私がしなければならなかったのは、TabControlDockingManagerに置き換えて、いくつかを修正することでした(Style)。

DockingManagerセットアップ(私はドキュメントのみ、ツール以外はありません。):私はAvalonDockのテンプレートセレクタを使用する必要はありませんでした

<avalonDock:DockingManager x:Name="tabDesigner" DocumentsSource="{Binding Items}"> 
    <avalonDock:DockingManager.LayoutItemContainerStyle> 
     <Style TargetType="{x:Type avalonDockControls:LayoutItem}" BasedOn="{StaticResource DocumentItem}"/> 
    </avalonDock:DockingManager.LayoutItemContainerStyle> 
    <avalonDock:DockingManager.DocumentPaneControlStyle> 
     <Style TargetType="{x:Type avalonDockControls:LayoutDocumentPaneControl}" BasedOn="{StaticResource DocumentPane}"/> 
    </avalonDock:DockingManager.DocumentPaneControlStyle> 
    <avalonDockLayout:LayoutRoot> 
     <avalonDockLayout:LayoutPanel Orientation="Horizontal"> 
      <avalonDockLayout:LayoutDocumentPane/> 
     </avalonDockLayout:LayoutPanel> 
    </avalonDockLayout:LayoutRoot> 
</avalonDock:DockingManager> 

、私はすでに以前TabControl用に設定されたDataTemplate Sを使用することができました。

私は(それがAvalonDockのモデル内にあるビューモデルにバインドする方法を見つけ出すには少し時間がかかりました)、ビューモデルと他のレイアウトの違いに結合する余分な操作を行うためにLayoutItemLayoutDocumentPaneControl、およびLayoutDocumentTabItemStyleのを修正:

<Style x:Key="DocumentItem" TargetType="{x:Type avalonDockControls:LayoutItem}"> 
    <Setter Property="Title" Value="{Binding Model.TabTitle}"/> 
    <Setter Property="CloseCommand" Value="{Binding Model.CloseConfirmCommand}"/> 
    <Setter Property="IsSelected" Value="{Binding Model.IsSelected, Mode=TwoWay}"/> 
</Style> 

<Style x:Key="DocumentPane" TargetType="{x:Type avalonDockControls:LayoutDocumentPaneControl}"> 
    ... 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type avalonDockControls:LayoutDocumentPaneControl}"> 
       <Grid ClipToBounds="true" SnapsToDevicePixels="true" KeyboardNavigation.TabNavigation="Local"> 
        ... 
        <Grid Panel.ZIndex="1" Background="{DynamicResource TabControlHeaderBrush}" > 
         ... 
         <avalonDockControls:DocumentPaneTabPanel x:Name="HeaderPanel" Grid.Column="0" IsItemsHost="true" Margin="4,0,16,0" Grid.Row="0" KeyboardNavigation.TabIndex="1"/> 
         <avalonDockControls:DropDownButton 
          ... 
          Style="{DynamicResource ToolBarHorizontalOverflowButtonStyle}" 
          Grid.Column="1"> 
          ... 
         </avalonDockControls:DropDownButton> 
        </Grid> 
        <Border x:Name="ContentPanel" 
          ... 
          CornerRadius="3"> 
         <Border 
          ... 
          > 
          <Border 
           ... 
           > 
           <ContentPresenter x:Name="PART_SelectedContentHost" 
               ContentSource="SelectedContent" 
               SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
          </Border> 
         </Border> 
        </Border> 
       </Grid> 
       <ControlTemplate.Triggers> 
        ... 
       </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
    <Setter Property="ItemContainerStyle"> 
     <Setter.Value> 
      <Style TargetType="{x:Type TabItem}"> 
       ... 
       <Setter Property="Template"> 
        <Setter.Value> 
         <ControlTemplate TargetType="{x:Type TabItem}"> 
          <Grid> 
           <ContentPresenter 
            x:Name="Content" 
            ContentSource="Header" 
            ... 
            SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
          </Grid> 
         </ControlTemplate> 
        </Setter.Value> 
       </Setter> 
      </Style> 
     </Setter.Value> 
    </Setter> 
    <Setter Property="ItemTemplate"> 
     <Setter.Value> 
      <DataTemplate> 
       <avalonDockControls:LayoutDocumentTabItem Model="{Binding}"/> 
      </DataTemplate> 
     </Setter.Value> 
    </Setter> 

    <Setter Property="ContentTemplate"> 
     <Setter.Value> 
      <DataTemplate> 
       <avalonDockControls:LayoutDocumentControl Model="{Binding}"/> 
      </DataTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

<Style TargetType="{x:Type avalonDockControls:LayoutDocumentTabItem}"> 
    <Setter Property="Template"> 
      <Setter.Value> 
      <ControlTemplate TargetType="{x:Type avalonDockControls:LayoutDocumentTabItem}"> 
       <ControlTemplate.Resources> 
        ... 
       </ControlTemplate.Resources> 
       <Grid x:Name="grid" Margin="8,1,8,0"> 
        ... 
        <Grid RenderTransformOrigin="0.5,0.5"> 
         ... 
         <StackPanel Orientation="Horizontal" Margin="3,0,2,0"> 
          <ContentPresenter x:Name="TabContent" Content="{Binding Model, RelativeSource={RelativeSource TemplatedParent}}" TextBlock.Foreground="{DynamicResource UnselectedTabText}" 
               ContentTemplate="{Binding DocumentHeaderTemplate, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type avalonDock:DockingManager}, Mode=FindAncestor}}" 
               ContentTemplateSelector="{Binding DocumentHeaderTemplateSelector, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type avalonDock:DockingManager}, Mode=FindAncestor}}" 
               Margin="5,2,5,2"/> 
          <Button 
           x:Name="TabItemButton" 
           Command="{Binding Path=Model.Content.CloseConfirmCommand, RelativeSource={RelativeSource TemplatedParent}}" 
           Content="X" 
           ... 
          /> 
          <StackPanel.ContextMenu> 
           <ContextMenu> 
            <MenuItem Header="{Binding Model.Content.CloseTabLabel, RelativeSource={RelativeSource TemplatedParent}}" Command="{Binding Model.Content.CloseTab, RelativeSource={RelativeSource TemplatedParent}}" ToolTip="{Binding Model.Content.CloseTabToolTipLabel, RelativeSource={RelativeSource TemplatedParent}}"></MenuItem> 
            <MenuItem Header="{Binding Model.Content.CloseOtherTabsLabel, RelativeSource={RelativeSource TemplatedParent}}" Command="{Binding Model.Content.CloseOtherTabs, RelativeSource={RelativeSource TemplatedParent}}" ToolTip="{Binding Model.Content.CloseOtherTabsToolTipLabel, RelativeSource={RelativeSource TemplatedParent}}"></MenuItem> 
            <MenuItem Header="{Binding Model.Content.NextTabLabel, RelativeSource={RelativeSource TemplatedParent}}" Command="{Binding Model.Content.NextTab, RelativeSource={RelativeSource TemplatedParent}}" ToolTip="{Binding Model.Content.NextTabToolTipLabel, RelativeSource={RelativeSource TemplatedParent}}"></MenuItem> 
           </ContextMenu> 
          </StackPanel.ContextMenu> 
         </StackPanel> 
        </Grid> 
       </Grid> 
       <ControlTemplate.Triggers> 
        ... 
       </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

これは最終結果の例である:

enter image description here

関連する問題