Popup is not a proper child of its parent window? - wpf

I'm trying to create a stylish window with icon in the top-right corner that is partly outside the window boundary. Since this is not directly possible (content falling outside the window is clipped), I'm using a Popup control for it.
<Popup Placement="Right" HorizontalOffset="-80" VerticalOffset="-40" IsOpen="True" AllowsTransparency="True"
PlacementTarget="{Binding RelativeSource={RelativeSource AncestorType=Grid}}">
<Image Source="pack://application:,,,/graphics/AdminIcon.png" Stretch="None" />
</Popup>
It works fine, as long as I don't switch between windows. Thereupon it looks like the Popup is neither a proper child of the Window, nor a fully separate window of its own; something in-between.
I'll try to explain it with two images:
Image1: Window loaded and popup showing nicely in the right-top corner:
Image2: ALT + TAB: Notepad somehow injects itself between Popup and Window
How do I solve this problem?

Instead of a Popup you may use a borderless, transparent Window:
<Window ...
WindowStyle="None" AllowsTransparency="True" Background="{x:Null}"
MouseLeftButtonDown="Window_MouseLeftButtonDown">
<Grid>
<Grid Margin="0,20,0,0" Background="White">
... window content goes here
</Grid>
<Image
Source="/graphics/AdminIcon.png" Stretch="None"
HorizontalAlignment="Right" VerticalAlignment="Top" />
</Grid>
</Window>
with this MouseLeftButtonDown handler
private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DragMove();
}
and perhaps a close button somewhere.

Related

Popup and Window's AllowsTransparency

As soon as I set AllowsTransparency to true in a Window and close a Popup in front of this Window, the Window is not redrawn and the popup still shows up on top of the Window.
If this Window lose focus or If I enter the "alt" key of the keyboard, the Window is redrawn and displays correctly.
To be more clear:
Without AllowTransparency
Popup shown:
Popup hidden:
With AllowTransparency
Popup shown:
Popup hidden:
XAML:
<Window x:Class="Tests.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="300" Width="1000"
WindowStyle="None"
AllowsTransparency="True">
<Grid>
<Rectangle Width="1000" Height="300" Fill="Red"></Rectangle>
<CheckBox x:Name="PopupCheckBox">
<TextBlock Text="Show popup"/>
</CheckBox>
<Popup IsOpen="{Binding ElementName=PopupCheckBox, Path=IsChecked}" Placement="Center">
<Rectangle Width="500" Height="500" Fill="Green" />
</Popup>
</Grid>
</Window>
I would like to know what is the cause of this behavior and how to fix/bypass it.
Thank you.
Edit
I tried to call InvalidateVisual in the handler of the popup's Closed event but it did not change the behavior:
public MainWindow()
{
InitializeComponent();
PopupTest.Closed += PopupTest_Closed;
}
void PopupTest_Closed(object sender, EventArgs e)
{
InvalidateVisual();
}
Edit 2
Ok so it appear that the graphic card driver is the cause of this behavior. I updated it to the latest one and while an artifact is still shown, it behaves differently (shown area of the popup is much smaller).
Closing this thread. Thanks to all.
As stated in the question's latest edit, the artifact is caused by outdated graphic card driver.
I can't tell you the cause but to fix this issue use the method InvalidateVisual on your window when closing the popup.
window.InvalidateVisual();

how to access the grids on silverlight

I have a button called test button an when I click on it I want to show a grid whose visbility is set to 0
I created a mouse button event (below) but my Grid (testGrid) is not available in the project.
private void testButton(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
testGrid.Opacity = 1;
}
it highlights testGrid red
new to SL so not sure whats going on here
** EDIT **
xml for the Grid
<Grid x:Name="testGrid" HorizontalAlignment="Left" Width="150" Margin="950,-77,0,0" Height="77" VerticalAlignment="Top" Opacity="0">
</Grid>
<Image x:Name="testButton" HorizontalAlignment="Right" Margin="0,1,180,3" Stretch="Fill" Width="53" Height="49" Cursor="Hand" Opacity="0.8" >
The reason that your grid might not be accessibly in the .cs file is if you have changed the class name in the .cs file, but not in the Xaml directive at the top of your .xaml file.
If these two mis match, visual studio won't be able to link up the two files and so you wouldn't be able to see the grid control in the code behind.
Other items with your code to consider:
Though Opacity will work an alternative I use more often is:
This will show the grid.
testGrid.Visibility = Visibility.Visible;
This will hide the grid.
testGrid.Visibility = Visibility.Collapsed;
Also, Your "Button" is an Image tag and not a button. It is an image with the same name as the method you are trying to call. You will either need to change your Image to allow for an on click event or change it to a button, something like
<Button Click="TestBUtton" Text="MyButton" />
And I'd enter that in the Xaml directly so that when you type in the click event handler it auto generates the method in the code behind for you.
try this:
On XAML
<Grid x:Name="testGrid" HorizontalAlignment="Left" Width="150" Margin="950,-77,0,0" Height="77" VerticalAlignment="Top" Opacity="0">
</Grid>
<Image x:Name="testButton" HorizontalAlignment="Right" Margin="0,1,180,3" Stretch="Fill" Width="53" Height="49" Cursor="Hand" Opacity="0.8" MouseLeftButtonDown="testButton" />
on the cs
private void testButton(object sender, System.Windows.Input.MouseButtonEventArgs e){
testGrid.Visibility = Visibility.Visible;
}

Silverlight MouseLeave showing inconistent behaviour

So, my problem is that the MouseLeave event only gets triggered if I move my cursor at a certain speed. Below is a Thumb with a Border. Click the thumb and keep the mouse button down. Move slowly outside the border = no event, Move fast outside the border = event.
<Grid x:Name="LayoutRoot" Background="White">
<Border BorderBrush="Black" BorderThickness="3" Width="200" Height="100"
MouseLeave="Border_MouseLeave">
<Thumb />
</Border>
</Grid>
private void Border_MouseLeave(object sender, MouseEventArgs e)
{
MessageBox.Show("Border_MouseLeave");
}
Is it a bug in silverlight or am I missing something?
Thanx
/Mike
Thanx for the anwers, here's an update:
It seems to have something to do with MouseCapture as Guy suggests. The reason being that I also get the problem using Button or a Rectangle that captures the mouse in code-behind.
If I put a Grid between the Thumb and the Border the problem disappears so I think I will go with that.
I also noticed a related problem as I played around some.
<Grid Width="200" Height="100" Background="Transparent"
MouseLeave="Border_MouseLeave">
<Button />
<Rectangle Width="40" Height="40" Fill="Violet"
HorizontalAlignment="Left" />
</Grid>
If I press the left button and move the cursor to the left over the Rectangle and out the MouseLeave event is not registered.
This is all very strange.

WPF Popup UI showing black

I am using a WPF Popup control, and it is showing the background as black. I put a StackPanel inside it with Background="Transparent", but that does not help.
<Popup PlacementTarget="{Binding ElementName=parentStackPanel}" Placement="Center"
IsOpen="False" Name="m_popWaitNotifier" PopupAnimation="None"
AllowsTransparency="False">
<StackPanel Orientation="Vertical" Background="Transparent">
<uc:CircularProgressBar x:Name="CB" StartupDelay="0"
RotationsPerMinute="20"
Height="25" Foreground="White"
Margin="12"/>
</StackPanel>
</Popup>
How does one make the background on Popup transparent (or any color)?
You need to set the AllowsTransparency="True" Popup Property to True
Here is an example:
<Grid>
<StackPanel>
<Button Click="Button_Click" Width="100" Height="20" Content="Click" />
<Popup x:Name="popup" Width="100" Height="100" AllowsTransparency="True">
<Grid Background="Transparent">
<TextBlock Text="Some Text" />
</Grid>
</Popup>
</StackPanel>
</Grid>
and the click handler
private void Button_Click(object sender, RoutedEventArgs e)
{
popup.Visibility = System.Windows.Visibility.Visible;
popup.IsOpen = true;
}
The base color of a Popup, or a Window for that matter, is black. You rarely see it for a Window because Window has a Background property and it defaults to a solid color, but if you set Window.Background to Transparent it will also be black. But Popup doesn't have a Background property and so, pardon the pun, this problem "pops up".
If you want the Popup to be transparent, you need to set AllowsTransparency="True". However, if you want the Popup to be a solid color, the simplest approach is to make the child of the Popup a Panel that supports the Background property and set that property to the color you desire and then set the child of the Panel to be the content you intended for the Popup in the first place. I suggest Grid as it won't affect the layout of your Popup. It's only effect will be to give you the background color you desire.
Make sure that the allow transparency is set to true, vertical and horizontal alignments are centered, and the height and width are set to Auto.
For example:
<Popup Name="popup1" Placement="Top" PlacementTarget="{Binding ElementName=button2}" AllowsTransparency="True" Height="Auto" Width="Auto" Panel.ZIndex="1" HorizontalOffset="-5" HorizontalAlignment="Center" VerticalAlignment="Center">
<StackPanel Height="92" HorizontalAlignment="Left" Margin="93,522,0,0" Name="stackPanelPop" VerticalAlignment="Top" Width="147">
</StackPanel>
</Popup>
Another possible cause:
using IsOpen="True" in markup before AllowTransparency="True"
Switching the order fixes it.
My guess is that the CircularProgressBar is actually causing the Black background. The only other way that this could happen is if there was a Style or something set on one of the controls (Popup or StackPanel or...).
Here is a quick-n-dirty example that shows a TextBlock in a popup when a checkbox is checked. The colors chosen are just to make sure things stand out visually:
<StackPanel x:Name="stackPanelLayout">
<StackPanel.Background>
<RadialGradientBrush Center="0.75, 0.75"
SpreadMethod="Reflect">
<GradientStop Color="LightBlue" Offset="0" />
<GradientStop Color="SeaGreen" Offset="0.5" />
<GradientStop Color="MidnightBlue" Offset="0.75" />
</RadialGradientBrush>
</StackPanel.Background>
<CheckBox x:Name="chkShowPopup"
FontSize="20"
Foreground="White"
Content="Show Popup" />
<Popup PlacementTarget="{Binding ElementName=stackPanelLayout}"
Placement="Center"
IsOpen="{Binding ElementName=chkShowPopup, Path=IsChecked}"
Name="m_popWaitNotifier"
PopupAnimation="Slide"
AllowsTransparency="True">
<StackPanel Orientation="Vertical" Background="Transparent">
<TextBlock Foreground="White" FontSize="30" FontWeight="Bold" Text="PopUp" />
</StackPanel>
</Popup>
</StackPanel>
So, two tests you can do to determine what is happening:
Replace the CircularProgressBar with a simple TextBlock or other control that you don't have a Style applied to.
Put the CircularProgressBar as a standalone control somewhere on your window, or on an otherwise blank test Window.
As per this article Why is my WPF Popup black and how do I get it positioned properly?
:
You need to set the AllowsTransparency property on the Popup to True, and set the PlacementTarget and Placement properties to control the position the Popup opens in.
As per the code in question:
<Popup PlacementTarget="{Binding ElementName=parentStackPanel}" Placement="Center" IsOpen="False" Name="m_popWaitNotifier" PopupAnimation="None" AllowsTransparency="False">
<StackPanel Orientation="Vertical" Background="Transparent">
<uc:CircularProgressBar x:Name="CB" StartupDelay="0" RotationsPerMinute="20" Height="25" Foreground="White" Margin="12"/>
</StackPanel>
</Popup>
the PlacementTarget is set to parentStackPanel, whereas the questioner has mentioned:
Hi Svetlozar: I tried this but it does
not work. For me though I do not have
a StackPanel outside the Popup, but I
have a StackPanel within the Popup
that holds a couple of control on it
The problem could be that Popup could not find the PlacementTarget 'parentStackPanel' because it does not exist.
The problem is that the grid is not orientation places it outside of the popup.
Remove VerticalAlignment and horizontalAlignment from all the controls inside the popup, and it will work correctly
Quite old, but may help someone: Add InitializeComponent(); in the constructor, it solved my problem:
class MyPopupClass : Popup {
/*
...
*/
public MyPopupClass () {
InitializeComponent();
/*
...
*/
}
/*
...
*/
}

How do I swallow the dropdown behavior inside an Expander.Header?

I would like to prevent an Expander from expanding/collapsing when users click inside the header area. This is basically the same question as Q 1396153, but I'd appreciate a more favorable answer :)
Is there a non-invasive way to do this? I am not sure exactly how to attach behavior to the Expander.Header content to prevent mouseclicks. I'm willing to float in content outside the expander itself via a fixed grid layout, but I'm not keen on the solution. Ideas?
XamlPad sample XAML:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Expander>
<Expander.Header><TextBlock>
When I click this text,
I don't want to trigger expansion/collapse! Only when I click the
expander button do I want to trigger an expand/collapse!
</TextBlock></Expander.Header>
<Grid Background="Red" Height="100" Width="100" >
</Grid>
</Expander>
</Page>
You can stop mouse clicks on the text box from being handled by your application.
XAML:
<Expander>
<Expander.Header>
<TextBlock MouseDown="TextBlock_MouseDown">
When I click this text,
I don't want to trigger expansion/collapse! Only when I click the
expander button do I want to trigger an expand/collapse!
</TextBlock>
</Expander.Header>
<Grid Background="Red" Height="100" Width="100" >
</Grid>
</Expander>
Code behind:
private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
}
I don't know if this is an abomination, but, I've moved the content out of the Expander.Header and done some Grid/fixed layout/Panel.ZIndex trickery to make it appear that the content is in the Expander.Header...but it's not. This works, but it's horrible.

Resources