Just to add on to NathanAW's great solution above, I thought I'd point out some context, such as where to place the C# code in this case. I'm still pretty new to WPF so I struggled at first to figure out where to put NathanAW's code. When I tried putting that code in the constructor for the UserControl that hosted my Popup, Window.GetWindow()
always returned Null
(so the "bump" code never executed). So I thought that other newbies might benefit from seeing things in context.
Before showing the C# in context, here's some example XAML context to show some relevant elements and their names:
<UserControl x:Class="MyNamespace.View1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<TextBlock x:Name="popupTarget" />
<Popup x:Name="myPopup"
Placement="Bottom"
PlacementTarget="{Binding ElementName=popupTarget}" >
(popup content here)
</Popup>
</UserControl>
Then in the code-behind, to avoid having Window.GetWindow()
return Null
, wire up a handler to the Loaded event to house NathanAW's code (see Peter Walke's comment on a similar stackoverflow discussion for example). Here's exactly how it all looked in my UserControl code-behind:
public partial class View1 : UserControl
{
// Constructor
public View1()
{
InitializeComponent();
// Window.GetWindow() will return Null if you try to call it here!
// Wire up the Loaded handler instead
this.Loaded += new RoutedEventHandler(View1_Loaded);
}
/// Provides a way to "dock" the Popup control to the Window
/// so that the popup "sticks" to the window while the window is dragged around.
void View1_Loaded(object sender, RoutedEventArgs e)
{
Window w = Window.GetWindow(popupTarget);
// w should not be Null now!
if (null != w)
{
w.LocationChanged += delegate(object sender2, EventArgs args)
{
var offset = myPopup.HorizontalOffset;
// "bump" the offset to cause the popup to reposition itself
// on its own
myPopup.HorizontalOffset = offset + 1;
myPopup.HorizontalOffset = offset;
};
// Also handle the window being resized (so the popup's position stays
// relative to its target element if the target element moves upon
// window resize)
w.SizeChanged += delegate(object sender3, SizeChangedEventArgs e2)
{
var offset = myPopup.HorizontalOffset;
myPopup.HorizontalOffset = offset + 1;
myPopup.HorizontalOffset = offset;
};
}
}
}