DocumentContent

Aug 1, 2008 at 5:08 PM
I have been working on WPF for the last two weeks and I am using the AvalonDock library.
I would like to know if there is any way to avoid closing a DocumentContent. Actually I don't even want the close button to show in the DocumentContent however if that is not possible, how can I stop the closing process especially for the home tab?
I have added the Unload event but couldn't find any variable that I can set to false regarding the closing issue.

As well, I have seen the AvalonDock sample and tried to follow some of the functions. I am having some problems with DocumentContent. If I try to open many documents and modify the way they are displayed then I decide to restore the default layout, the documents keep focused at the same location however if I do the same with DockableContent and then decide to restore the default layout, it works  well.
Is it possible to drag documents anywhere in the application then being able to restore the default layout, thus by having each document positioned at the same place as it was when I runned the application?
And how can I get all DocumentContent that are present in the application wherever they are positioned knowing that they all have the very supreme parent: DockPanel. I mean I need to able to loop over all DocumentContent.

I would appreciate any help. Thank you very much in advance.
Best Regards.
Aug 5, 2008 at 3:56 AM
To avoid closing of the Document Content you can add the 2 events names closing and closed event in the DocumentPane class as mentioned below

 

public delegate void DocumentPaneClosingEventHandler(object sender, CancelEventArgs e);

 

 

public delegate void DocumentPaneClosedEventHandler(object sender, EventArgs e);

and in the ExecutedCloseCommand(object sender, ExecutedRoutedEventArgs e)  method just raise the above 2 methods. Again i have copy pasted the code i had implemented below

 

 

public void ExecutedCloseCommand(object sender,

 

 

ExecutedRoutedEventArgs e)

 

{

 

if (GetManager() == null)

 

 

return;

 

 

CancelEventArgs cancelEventArgs = new CancelEventArgs(false);

 

 

DockableContent dockableContent = this.SelectedItem as DockableContent;

 

 

if (dockableContent != null)

 

{

RaiseDocumentPaneClosing(dockableContent, cancelEventArgs);

 

if (cancelEventArgs.Cancel)

 

 

return;

 

GetManager().Hide(dockableContent);

RaiseDocumentPaneClosed();

}

 

else

 

 

 

{

 

 

DocumentContent documentContent = this.SelectedItem as DocumentContent;

 

 

if (documentContent != null)

 

{

RaiseDocumentPaneClosing(documentContent, cancelEventArgs);

 

if (cancelEventArgs.Cancel)

 

 

return;

 

Items.Remove(documentContent);

RaiseDocumentPaneClosed();

}

CheckContentsEmpty();

}

}


May be you can just copy paste the method in the documentPane class




and in the class where you are using the DockingManager of avalon dock subscribe to these 2 events something like this

 

documentPane =

new DocumentPane();

 

documentPane.Closing += OnDocumentPaneClosing;

documentPane.Closed += OnDocumentPaneClosed;

 


and in the closing event handler you can check whether to close the document content or not..




As far as getting all the document opened/displayed you can use the property 

DockingManager.Documents. This shud give you the list of all opened document (Correct me if i m wrong here :))


I hope this helps you


Regards,

 

 



 

Aug 5, 2008 at 1:01 PM
Yes, the solution proposed works, but you need to change AvalonDock source code. I can suggest you another approach that is more WPF friendly.
Add a command binding to ApplicationCommands.Close command and set CanExecute a false.
This is an example:

 

/// <summary>

 

 

/// Interaction logic for DemoDocument.xaml

 

 

/// </summary>

 

 

public partial class DemoDocument : DocumentContent

 

{

 

public DemoDocument()

 

{

InitializeComponent();

}

 

public override void OnApplyTemplate()

 

{

 

base.OnApplyTemplate();

 

ContainerPane.CommandBindings.Add(

new CommandBinding(

 

 

ApplicationCommands.Close, null, new CanExecuteRoutedEventHandler(this.OnCanClose)));

 

}

 

 

private void OnCanClose(object sender, CanExecuteRoutedEventArgs e)

 

{

e.Handled =

true;

 

e.CanExecute =

false;

 

}

}

Ado
Aug 6, 2008 at 3:40 PM
I would like to thank you both for replying.

Actually I am not sure if I got what you meant regarding the WPF friendly approach.
I have a main class which is of type Window and contains the AvalonDock.DocumentPane which in turns contains many DocumentContent.
What I want is if there is any way in order to hide the close button?
I added a close button in the upper menu and do not want the DocumentPane default close button to show. Is that possible?

If not, where in the main class should I add the CommandBinding? Should the DocumentPane be binded?

Thank you again.
Looking for your reply.
Aug 7, 2008 at 8:52 AM
Hi, if want to hide the close button, or in general change the appereance of AvalonDock, you have to restyle it.
Follows a DocumetPane style without close button (put it in a resource dictionary of your application).

 

<Style TargetType="{x:Type ad:DocumentPane}">

 

 

<Setter Property="Template">

 

 

<Setter.Value>

 

 

<ControlTemplate TargetType="{x:Type ad:DocumentPane}" >

 

 

<ControlTemplate.Resources>

 

 

<ContextMenu x:Key="DocumentsListMenu" StaysOpen="True" ><!--ItemTemplate="{StaticResource ManagedContentHeaderDataTemplate}"-->

 

 

<ContextMenu.ItemContainerStyle>

 

 

<Style TargetType="{x:Type MenuItem}">

 

 

<Setter Property="CommandParameter" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Header}"/>

 

 

<Setter Property="Command" Value="ad:DocumentPane.ActivateDocumentCommand"/>

 

 

<Setter Property="Template">

 

 

<Setter.Value>

 

 

<ControlTemplate TargetType="MenuItem">

 

 

<Border x:Name="intBorder" BorderThickness="1" Background="{TemplateBinding Background}" CornerRadius="2">

 

 

<Grid>

 

 

<Grid.ColumnDefinitions>

 

 

<ColumnDefinition Width="Auto"/>

 

 

<ColumnDefinition Width="*"/>

 

 

</Grid.ColumnDefinitions>

 

 

<Image Margin="5,2,5,2" Source="{Binding Path=IconSource, Converter={StaticResource resourcePathConverter}}" Grid.Column="0" Height="16" Width="16" VerticalAlignment="Center"/>

 

 

<TextBlock Margin="5,2,20,2" Text="{Binding Path=Title}" Grid.Column="1" VerticalAlignment="Center"/>

 

 

</Grid>

 

 

</Border>

 

 

<ControlTemplate.Triggers>

 

 

<DataTrigger Binding="{Binding Path=IsSelected}" Value="True">

 

 

<Setter Property="TextBlock.FontWeight" Value="Bold"/>

 

 

</DataTrigger>

 

 

<Trigger Property="IsMouseOver" Value="true">

 

 

<Setter Property="Background" TargetName="intBorder">

 

 

<Setter.Value>

 

 

<SolidColorBrush Color="{DynamicResource {x:Static SystemColors.ActiveCaptionColorKey}}" Opacity="0.3"/>

 

 

</Setter.Value>

 

 

</Setter>

 

 

<Setter Property="BorderBrush" TargetName="intBorder" Value="{DynamicResource {x:Static SystemColors.ActiveCaptionBrushKey}}"/>

 

 

</Trigger>

 

 

</ControlTemplate.Triggers>

 

 

</ControlTemplate>

 

 

</Setter.Value>

 

 

</Setter>

 

 

</Style>

 

 

</ContextMenu.ItemContainerStyle>

 

 

</ContextMenu>

 

 

</ControlTemplate.Resources>

 

 

<Border>

 

 

<Grid>

 

 

<Grid.RowDefinitions>

 

 

<RowDefinition Height="20"/>

 

 

<RowDefinition Height="*"/>

 

 

</Grid.RowDefinitions>

 

 

<Border x:Name="PART_Header"

 

 

Grid.Row="0"

 

 

Focusable="False"

 

 

BorderThickness="1,1,1,0">

 

 

<DockPanel LastChildFill="True">

 

 

 

<Button DockPanel.Dock="Right" Width="18" Style="{StaticResource PaneHeaderCommandStyle}" Command="ad:DocumentPane.ShowDocumentsListMenuCommand">

 

 

<Image Source="Images\PinMenu.png" Width="17" Height="16" Stretch="Uniform"/>

 

 

</Button>

 

 

<ad:DocumentTabPanel

 

 

x:Name="paneTabsPanel"

 

 

Panel.ZIndex ="1"

 

 

KeyboardNavigation.TabIndex="2"

 

 

IsItemsHost="True"

 

 

Margin="10,2,0,0"

 

 

TabItemStyle="{StaticResource DocumentTabItemStyle}"/>

 

 

</DockPanel>

 

 

</Border>

 

 

<Grid Grid.Row="1">

 

 

<Border

 

 

BorderThickness="5"

 

 

BorderBrush="#FFC1D2EE"

 

 

CornerRadius="3"

 

 

Background="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedItem.Background}" />

 

 

<Border BorderThickness="2" BorderBrush="#FFD6E2F8" CornerRadius="3" Margin="1" >

 

 

<ContentPresenter

 

 

Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedItem.Content}"

 

 

Margin="2"

 

 

KeyboardNavigation.TabNavigation="Local"

 

 

KeyboardNavigation.DirectionalNavigation="Contained"

 

 

KeyboardNavigation.TabIndex="1"

 

 

/>

 

 

</Border>

 

 

</Grid>

 

 

</Grid>

 

 

</Border>

 

 

<ControlTemplate.Triggers>

 

 

<EventTrigger RoutedEvent="Window.Loaded">

 

 

<BeginStoryboard>

 

 

<Storyboard>

 

 

<DoubleAnimation

 

 

Storyboard.TargetProperty="Opacity"

 

 

From="0" To="1" Duration="0:0:0.200" />

 

 

</Storyboard>

 

 

</BeginStoryboard>

 

 

</EventTrigger>

 

 

</ControlTemplate.Triggers>

 

 

</ControlTemplate>

 

 

</Setter.Value>

 

 

</Setter>

 

 

</Style>


Ado

 

Aug 8, 2008 at 1:52 PM
Again I would like to thank you for your help.

Actually I have added the above code in a resource dictionary in my application but got the following errors:
   - StaticResource reference 'resourcePathConverter' was not found
   - StaticResource reference 'PaneHeaderCommandStyle' was not found
  - PinMenu.png image is missing
Would you please send me the resources that you defined?

I would like to make sure if the style that you defined is just for a single document or not?

Let me redefine what my problem is just to make sure that we are both on the same track.
I have a document pane that contains several document contents. I want to be able to switch from a content to another (switching between tabs). I just don't want the close button to show. How can I hide it for all the documents?or more precisely to the document pane knowing that as I just said, it contains several documents.
 
I am really sorry for bothering you.
Regards

Aug 8, 2008 at 3:43 PM
No bothering, no problem. :)
Just to clarify, a DocumentPane is an ItemsControl, which items are a collection of DocumentContent. If change the style of DocumentPane you are affecting the appearance of all the documents, or if you prefer of the selected item. If you donwload the source code of AvalonDock you can find all the resources you need under AvalonDock\Resources, actually the style I provided is simply a copy&paste of the default one you can find in AvalonDock\Resources\DocumentPaneStyles.xaml.
Ado
Aug 8, 2008 at 5:15 PM
Thank you very much. It worked out! :D
Actually I was using an older version and trying to use the code you posted so had some problems. I referenced the latest release, overriden the DocumentPane Style by hiding the close button. That's all!

Best Regards,
Lara