ContentControl 风格的弹出窗口不更新

Popup in style of ContentControl not updating

我有一个 ContentControl,其样式包含一个包装文本框的弹出窗口。我知道这听起来有点令人困惑,但我将在下面 post 一些代码。当大写锁定键打开时,会显示弹出窗口,但是当 window 被拖动时,弹出窗口不会随之移动。

我需要弄清楚如何以他们的样式更新弹出窗口的位置。

这个 ContentControl 在 window 和 UserControl 上都使用,所以这就是我试图在样式中解决这个问题的原因。

这个问题与其他一些问题不同,因为我试图用风格而不是代码来解决它。

内容控制:

public class ShowCapLockWarningControler : ContentControl
{

    static ShowCapLockWarningControler()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(ShowCapLockWarningControler), new FrameworkPropertyMetadata(typeof(ShowCapLockWarningControler)));
    }

    public static readonly DependencyProperty ShowMessageProperty =
        DependencyProperty.Register(Reflection.GetPropertyName<ShowCapLockWarningControler>(i => i.ShowMessage), typeof(bool),
                                    typeof(ShowCapLockWarningControler), new PropertyMetadata(false));

    public bool ShowMessage
    {
        get { return (bool)GetValue(ShowMessageProperty); }
        set { SetValue(ShowMessageProperty, value); }
    }

    public ShowCapLockWarningControler()
    {
        IsKeyboardFocusWithinChanged += (s, e) => RecomputeShowMessage();
        PreviewKeyDown += (s, e) => RecomputeShowMessage();
        PreviewKeyUp += (s, e) => RecomputeShowMessage();
    }

    private void RecomputeShowMessage()
    {
        ShowMessage = IsKeyboardFocusWithin && Console.CapsLock;
    }
}

如何使用:

<controls:ShowCapLockWarningControler Grid.Row="1" Grid.Column="2" Style="{DynamicResource CaplockWarning}">
    <PasswordBox  Width="150" Name="PasswordBox" PasswordChanged="HandlePasswordChanged" VerticalContentAlignment="Center" 
                 KeyDown="HandlePasswordBoxEnterPressed"/>
</controls:ShowCapLockWarningControler>

样式字典中的样式:

<Style x:Key="CaplockWarning"  TargetType="{x:Type controls:ShowCapLockWarningControler}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type controls:ShowCapLockWarningControler}">
                <Grid>
                    <ContentPresenter Name="Presenter"/>
                    <Popup Placement="Bottom" PlacementTarget="{Binding ElementName=Presenter}" Name="BalloonPopup"  AllowsTransparency="True"
                           IsOpen="{TemplateBinding ShowMessage}"  >
                        <!-- Visual of the popup-->                      
                    </Popup>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

使用Window.LocationChanged eventPopup.Placement = AbsolutePointPopup.HorizontalOffsetPopup.VerticalOffset

在下面的示例中,PopupContentControl's Loaded 事件被触发时出现。当 Window 更改其位置时,我们会更改相关的 Popup 属性。

代码:

<ContentControl x:Name="CntCtrl" Height="35" Content="Some content" Loaded="CntCtrl_Loaded_1"/>

<Popup PlacementTarget="{Binding ElementName=CntCtrl}" Placement="AbsolutePoint"  x:Name="Popup1">
    <ListBox>
        <ListBoxItem>item1</ListBoxItem>
        <ListBoxItem>item1</ListBoxItem>
        <ListBoxItem>item1</ListBoxItem>
        <ListBoxItem>item1</ListBoxItem>
        <ListBoxItem>item1</ListBoxItem>
        <ListBoxItem>item1</ListBoxItem>
        <ListBoxItem>item1</ListBoxItem>
    </ListBox>
</Popup>

代码:

private void Window_LocationChanged_1(object sender, EventArgs e)
{        
    Point ptb = CntCtrl.PointToScreen(new Point(0, 0));
    Popup1.HorizontalOffset = ptb.X;
    Popup1.VerticalOffset = ptb.Y + CntCtrl.Height;
}

private void CntCtrl_Loaded_1(object sender, RoutedEventArgs e)
{
    Popup1.IsOpen = true;
    Point ptb = CntCtrl.PointToScreen(new Point(0, 0));
    Popup1.HorizontalOffset = ptb.X;
    Popup1.VerticalOffset = ptb.Y + CntCtrl.Height;
}