Search code examples
c#wpfuser-interfaceavalondock

Overlaying AvalonDock floating windows; zIndex ignored


I'm trying to style AvalonDock floating windows in such a way that I can show an overlay over all of them. I'm planning to use this for a dialog service, who could then show "modal" dialogs by overlaying all floating windows with a semi-transparent solid brush.

My idea was to modify the style for LayoutAnchorableFloatingWindwoControl. The original style from the generic theme can be found below - including my commented out addition of an overlay grid:

<Style x:Key="{x:Type avalonDockControls:LayoutAnchorableFloatingWindowControl}" TargetType="{x:Type avalonDockControls:LayoutAnchorableFloatingWindowControl}">
    <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
    <Setter Property="shell:WindowChrome.WindowChrome">
        <Setter.Value>
            <shell:WindowChrome
                ResizeBorderThickness="10"
                CaptionHeight="16"
                CornerRadius="3,3,3,3"
                GlassFrameThickness="0"
                ShowSystemMenu="True"/>
        </Setter.Value>
    </Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type avalonDockControls:LayoutAnchorableFloatingWindowControl}">
                <Grid>

                  <!-- My overlay grid:
                    <Grid x:Name="OVERLAY_GRID" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Red" Panel.ZIndex="100000"/> 
                  -->

                    <Border  x:Name="WindowBorder" BorderThickness="3" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" BorderBrush="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}">
                        <Grid Margin="3">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="16"/>
                                <RowDefinition Height="*"/>
                            </Grid.RowDefinitions>
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*"/>
                                    <ColumnDefinition Width="Auto"/>
                                    <ColumnDefinition Width="Auto"/>
                                    <ColumnDefinition Width="Auto"/>
                                </Grid.ColumnDefinitions>

                                <Border
                                    Visibility="{Binding Path=Model.IsSinglePane, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BoolToVisibilityConverter}}">
                                    <avalonDockControls:DropDownControlArea 
                                        DropDownContextMenu="{Binding Model.Root.Manager.AnchorableContextMenu, RelativeSource={RelativeSource TemplatedParent}}"
                                        DropDownContextMenuDataContext="{Binding Path=SingleContentLayoutItem, RelativeSource={RelativeSource TemplatedParent}}">
                                        <ContentPresenter Content="{Binding Model.SinglePane.SelectedContent, RelativeSource={RelativeSource TemplatedParent}}" 
                                              ContentTemplate="{Binding Model.Root.Manager.AnchorableTitleTemplate, RelativeSource={RelativeSource TemplatedParent}}"
                                              ContentTemplateSelector="{Binding Model.Root.Manager.AnchorableTitleTemplateSelector, RelativeSource={RelativeSource TemplatedParent}}"/>
                                    </avalonDockControls:DropDownControlArea>
                                </Border>


                                <avalonDockControls:DropDownButton
                                    x:Name="SinglePaneContextMenu" ........../>
                                </avalonDockControls:DropDownButton>

                                <Button ...........>
                                </Button>

                                <Button ........>
                                </Button>

                                <Button .........>
                                </Button>
                            </Grid>
                            <ContentPresenter
                                Content="{TemplateBinding Content}" Grid.Row="1"/>
                        </Grid>
                    </Border>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="WindowState" Value="Maximized">
                        <Setter Property="Padding" Value="3" TargetName="WindowBorder"/>
                    </Trigger>
                    <Trigger Property="IsKeyboardFocused" Value="True">
                        <Setter TargetName="WindowBorder"  Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

When I'm using the original MVVMTestApp with the regular generic theme, a floating windlow looks as follows:

Regular generic theme

When I uncomment my OVERLAY_GRID, you would expect the entire window to be hidden by a giant red block. However, there's an issue...

The content-presenter is in front, even though it should not be

I'm at a complete loss what causes this. I've already tried giving the WindowBorder as well as the ContentPresenter explicitly lower Panel.ZIndex values, but that didn't help.

I've also wrapped the WindowBorder in an AdornerDecorator element, then tried overlaying the adorner layer in code, but I faced the same issue; the ContentControl was still on top. I can't figure out what's happening here.

AvalonDock derives classes from HwndHost to display its floating windows - could this cause the Airpsace problem resulting in my issue? Then again, I actually thought this only happens when you mix in WinForms, while all hosted elements are purely WPF as far as I know.

Does anyone know what causes this - or even better, how to fix this?


Solution

  • Just for reference if anyone else is looking for a solution in the future, I discussed this with the developers here

    http://wpftoolkit.codeplex.com/discussions/651639

    my solution was to replace FloatingWindowContentHost - which uses HwndHost for WinForms compatibility - with another control (e.g. ContentPresenter). Relatively easy fix, as long as you don't plan to host any WinForms in there. It does require you to recompile AvalonDock yourself though as this is a code change.