I make a Wpf code, which create the Popup from C# code. And I hope to place the Popup on the right side of a UserControl, but this only happens when I set popup.Placement = PlacementMode.Left;
Quite strange!
MainWindow
has a Grid
called MyGrid
.UserControl
called MyUserControl
will be embedded in MyGrid
.This is the UserControl xaml code:
<Grid Background="AliceBlue" Width="270" Height="100">
<Button Width="50"
Height="20"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Click="TestButton_Click"/>
</Grid>
C# code as below.
My idea is to transfer a parameter (MyGrid in MainWindow) to the UserControl (MyUserControl) when creating it in MainWindow.
public partial class MyUserControl : UserControl
{
UIElement Parent = null;
public delegate void TestButtonMouseClick(UIElement target);
public static event TestButtonMouseClick ETestButtonMouseClick;
public MyUserControl(UIElement parent)
{
InitializeComponent();
this.Parent = parent;
}
private void TestButton_Click(object sender, RoutedEventArgs e)
{
ETestButtonMouseClick?.Invoke(Parent);
}
}
For the MainWindow, its xaml code is as below.
This MyGrid could be anywhere in the MainWindow, and I use it as the container of the UserControl.
When click the button, the delegate will transfer the paramter (MyGrid) as target of the Popup's PlacementTarget.
Finally, when I set popup.Placement = PlacementMode.Left
; then as the picture shown above: the Popup appears on the right side of the UserControl. And if I set popup.Placement = PlacementMode.Right
, then the Popup will appear on the left side of the UserControl. Why?
The workable demo project can be found here: https://github.com/tomxue/MyPopupIssue.git
<Grid>
<Grid x:Name="MyGrid"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="270"
Height="100"/>
</Grid>
And its C# code behind is:
public MainWindow()
{
InitializeComponent();
MyUserControl userControl = new MyUserControl(MyGrid);
MyGrid.Children.Add(userControl);
MyUserControl.ETestButtonMouseClick += MyUserControl_ETestButtonMouseClick;
}
private void MyUserControl_ETestButtonMouseClick(UIElement target)
{
Application.Current.Dispatcher.InvokeAsync(new Action(() =>
{
Popup popup = new Popup();
popup.AllowsTransparency = true;
popup.PlacementTarget = target;
popup.HorizontalOffset = 10;
popup.VerticalOffset = 41;
popup.Placement = PlacementMode.Left;
popup.StaysOpen = false;
TextBlock myTextBlock = new TextBlock();
myTextBlock.HorizontalAlignment = HorizontalAlignment.Center;
myTextBlock.VerticalAlignment = VerticalAlignment.Center;
myTextBlock.Width = 166;
myTextBlock.Height = 170;
myTextBlock.Text = "Just a test.";
myTextBlock.FontSize = 22;
myTextBlock.Foreground = new SolidColorBrush(Colors.Red);
myTextBlock.Background = new SolidColorBrush(Colors.Yellow);
popup.Child = myTextBlock;
popup.IsOpen = true;
}));
}
More: I tested yeaterday night at home. And just now I tested again at office. Below picture shows my issue again. And I use Visual Studio 2022 Community version.
It's an issue with touch screen support. You have definitely touch screen support and "Sir Rufo" doesn't. So on touch devices Left and Right are swapped (right/left handedness support can maybe also impact the behavior).
Workaround:
var isTouchDev = Tablet.TabletDevices.OfType<TabletDevice>().Any(dev => dev.Type == TabletDeviceType.Touch);
var popup = new Popup();
popup.AllowsTransparency = true;
popup.Placement = isTouchDev ? PlacementMode.Right : PlacementMode.Left;
popup.PlacementTarget = target;
popup.VerticalOffset = 41;
popup.HorizontalOffset = isTouchDev ? -10 : 10;