WPF - How can I place a usercontrol over an Adorne

2019-02-09 01:54发布

问题:

alt text http://img42.imageshack.us/img42/4161/blinkthru.png

I'm trying to get the validation to not show through my custom modal dialog. I've tried setting the zindex of the dialog and and of the elements in this template. Any ideas?

This is coming from a validation template:

<ControlTemplate x:Key="ValidationTemplate">
        <DockPanel>
            <TextBlock Foreground="Red" FontSize="20" Panel.ZIndex="-10">!</TextBlock>
            <Border Name="validationBorder" BorderBrush="Red" BorderThickness="2" Padding="1" CornerRadius="3" Panel.ZIndex="-10">
                <Border.Resources>
                    <Storyboard x:Key="_blink">
                        <ColorAnimationUsingKeyFrames AutoReverse="True" BeginTime="00:00:00" Storyboard.TargetName="validationBorder" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" RepeatBehavior="Forever">
                            <SplineColorKeyFrame KeyTime="00:00:1" Value="#00FF0000"/>
                        </ColorAnimationUsingKeyFrames>
                    </Storyboard>
                </Border.Resources>
                <Border.Triggers>
                    <EventTrigger RoutedEvent="FrameworkElement.Loaded">
                        <BeginStoryboard Storyboard="{StaticResource _blink}" />
                    </EventTrigger>
                </Border.Triggers>
                <AdornedElementPlaceholder/>
            </Border>
        </DockPanel>
    </ControlTemplate>

The dialog:

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    x:Class="GunMiser.Controls.PendingChangesConfirmationDialog"
    Height="768" Width="1024" mc:Ignorable="d">
    <Grid Background="White">
        <Rectangle x:Name="MainRectangle" Margin="0,0,0,0" Style="{DynamicResource UserControlOverlayRectangleStyle}" Opacity="0.85"/>
        <Border Margin="288,250,278,288" Background="#FF868686" BorderBrush="Black" BorderThickness="1">
            <Border.Effect>
                <DropShadowEffect Color="#FFB6B2B2"/>
            </Border.Effect>
            <TextBlock x:Name="textBlockMessage" Margin="7,29,7,97" TextWrapping="Wrap" d:LayoutOverrides="VerticalAlignment" TextAlignment="Center"/>
        </Border>
        <Button x:Name="OkButton" Click="OkButton_Click" Margin="313,0,0,328" VerticalAlignment="Bottom" Height="24" Content="Save Changes" Style="{DynamicResource GunMiserButtonStyle}" HorizontalAlignment="Left" Width="103"/>
        <Button Click="CancelButton_Click" Margin="453.294,0,456,328" VerticalAlignment="Bottom" Height="24" Content="Cancel Changes" Style="{DynamicResource GunMiserButtonStyle}"/>
        <Button Click="CancelActionButton_Click" Margin="0,0,304,328" VerticalAlignment="Bottom" Height="24" Content="Go Back" Style="{DynamicResource GunMiserButtonStyle}" HorizontalAlignment="Right" Width="114.706"/>
    </Grid>
</UserControl>

And the overall window is:

<Window x:Class="GunMiser.Views.Shell"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:cal="http://www.codeplex.com/CompositeWPF"
    xmlns:controls="clr-namespace:GunMiser.Controls;assembly=GunMiser.Controls"
    Title="Gun Miser"
    Height="768" Width="1024">
    <Canvas>
        <controls:PendingChangesConfirmationDialog x:Name="PendingChangesConfirmationDialog" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" Width="1008" Height="730" Visibility="Collapsed" Panel.ZIndex="100" />
        <ContentControl x:Name="FilterRegion" cal:RegionManager.RegionName="FilterRegion" Width="326" Height="656" Canvas.Top="32" VerticalAlignment="Top" HorizontalAlignment="Left" />
        <ContentControl Name="WorkspaceRegion" cal:RegionManager.RegionName="WorkspaceRegion" Width="678" Height="726" Canvas.Left="330" VerticalAlignment="Top" HorizontalAlignment="Left"/>
        <Button Click="GunsButton_Click" Width="75" Height="25" Content="Guns" Canvas.Top="3" Style="{DynamicResource GunMiserButtonStyle}"/>
        <Button Click="OpticsButton_Click" Width="75" Height="25" Content="Optics" Canvas.Left="81" Canvas.Top="3" Style="{DynamicResource GunMiserButtonStyle}"/>
        <Button Click="SettingsButton_Click" Width="56" Height="28" Content="Settings" Canvas.Left="944" Style="{DynamicResource GunMiserButtonStyle}" HorizontalAlignment="Left" VerticalAlignment="Top"/>
        <Button Click="AccessoriesButton_Click" Width="75" Height="25" Content="Accessories" Canvas.Left="239" Canvas.Top="3" Style="{DynamicResource GunMiserButtonStyle}"/>
        <Button Click="AmmunitionButton_Click" Width="75" Height="25" Content="Ammunition" Canvas.Left="160" Canvas.Top="3" Style="{DynamicResource GunMiserButtonStyle}"/>

    </Canvas>
</Window>

回答1:

You problem is that the error template is shown in the adorner layer which in your case will be at the root window.

If you were to change your code to the following you wouldn't have a problem, because there would be a separate adorner layer created around the rest of you controls.

<Window x:Class="GunMiser.Views.Shell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cal="http://www.codeplex.com/CompositeWPF"
xmlns:controls="clr-namespace:GunMiser.Controls;assembly=GunMiser.Controls"
Title="Gun Miser"
Height="768" Width="1024">
<Canvas>        
    <AdornerDecorator>
        <Canvas>
            <ContentControl x:Name="FilterRegion" cal:RegionManager.RegionName="FilterRegion" Width="326" Height="656" Canvas.Top="32" VerticalAlignment="Top" HorizontalAlignment="Left" />
            <ContentControl Name="WorkspaceRegion" cal:RegionManager.RegionName="WorkspaceRegion" Width="678" Height="726" Canvas.Left="330" VerticalAlignment="Top" HorizontalAlignment="Left"/>
            <Button Click="GunsButton_Click" Width="75" Height="25" Content="Guns" Canvas.Top="3" Style="{DynamicResource GunMiserButtonStyle}"/>
            <Button Click="OpticsButton_Click" Width="75" Height="25" Content="Optics" Canvas.Left="81" Canvas.Top="3" Style="{DynamicResource GunMiserButtonStyle}"/>
            <Button Click="SettingsButton_Click" Width="56" Height="28" Content="Settings" Canvas.Left="944" Style="{DynamicResource GunMiserButtonStyle}" HorizontalAlignment="Left" VerticalAlignment="Top"/>
            <Button Click="AccessoriesButton_Click" Width="75" Height="25" Content="Accessories" Canvas.Left="239" Canvas.Top="3" Style="{DynamicResource GunMiserButtonStyle}"/>
            <Button Click="AmmunitionButton_Click" Width="75" Height="25" Content="Ammunition" Canvas.Left="160" Canvas.Top="3" Style="{DynamicResource GunMiserButtonStyle}"/>
        </Canvas>
    </AdornerDecorator>
    <controls:PendingChangesConfirmationDialog x:Name="PendingChangesConfirmationDialog" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" Width="1008" Height="730" Visibility="Collapsed" Panel.ZIndex="100" />
</Canvas>



回答2:

Alternatively, if you want to change just the style of the element (it's background, foreground, etc) and not it's whole ControlTemplate (which includes the adorner), you can set the Validation.ErrorTemplate so that it doesn't have a border, or exclamation point, then use a style trigger to change the style based on the property "Validation.HasError".

<Style TargetType="{x:Type TextBlock}" x:Key="TextBlockErrorStyle">
    <Setter Property="Validation.ErrorTemplate">
        <Setter.Value>
            <ControlTemplate>
                <!-- this gets rid of all adornment INCLUDING THE DEFAULT RED BORDER -->
                <AdornedElementPlaceholder Name="controlWithError" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="true">
            <Setter Property="Foreground" Value="Red"/>
            <Setter Property="Background" Value="MistyRose"/>
            <Setter Property="ToolTip" 
                Value="{Binding RelativeSource={RelativeSource Self},
                Path=(Validation.Errors)[0].ErrorContent}"/>
        </Trigger>
    </Style.Triggers>

</Style>