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 event
、Popup.Placement = AbsolutePoint
、Popup.HorizontalOffset
、Popup.VerticalOffset
。
在下面的示例中,Popup
在 ContentControl'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;
}
我有一个 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 event
、Popup.Placement = AbsolutePoint
、Popup.HorizontalOffset
、Popup.VerticalOffset
。
在下面的示例中,Popup
在 ContentControl'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;
}