Popup and Window's AllowsTransparency - wpf

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();

Related

How to center BusyIndicator to the center of MainWindow?

I created sample Wpf application and installed Extended WPF Toolkit (NuGet package). Here's my xaml code for showing BusyIndicator.
<Window x:Class="WpfApp3.Progress"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:local="clr-namespace:WpfApp3"
mc:Ignorable="d"
WindowStyle="None"
BorderThickness="0"
Title=""
VerticalAlignment="Center"
HorizontalAlignment="Center"
SizeToContent="WidthAndHeight"
d:DesignWidth="300"
d:DesignHeight="300">
<xctk:BusyIndicator IsBusy="True"
HorizontalAlignment="Center"
VerticalAlignment="Center"></xctk:BusyIndicator>
</Window>
Showing the progress window is triggered with this code:
private void Button_Click(object sender, RoutedEventArgs e)
{
Progress w = new Progress
{
Owner = Application.Current.MainWindow,
WindowStartupLocation = WindowStartupLocation.CenterOwner
};
w.Show();
}
My question is simple. How to show BusyIndicator in the middle of the MainWindow screen. As Shown from the picture below it's not centered as it should be. Note that I use SizeToContent="WidthAndHeight"
Having a seperate window to display the busy indicator and will result in unwanted behaviour. What happens if the original window is maximised, moved etc.?
Consider adding the busy indicator to the main screen. Usually I create an overlay region that is used to display message dialogs, progress bars etc..
<Window>
<Grid>
<Application stuff ....>
</Application stuff>
<ContentControl regions:RegionManager.RegionName="OverlayRegion"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
</Grid>
</Window>
I'm using Prism here but you can replace the ContentControl with anything, such as the BusyIndicator and manipulate the visibility of the control.
Solved it by removing Window.SizeToContent property and by adding VerticalAlignment and HorizontalAlignment properties to BusyIndicator (actually now I used spinner, but this doesn't make any difference in solution).
<Window x:Class="Test.Progress"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:extToolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit/extended"
WindowStyle="None"
AllowsTransparency="True"
BorderThickness="0"
Title=""
WindowStartupLocation="CenterOwner"
ShowInTaskbar="False"
Background="Transparent"
d:DesignWidth="200"
d:DesignHeight="200"
MaxWidth="250"
MaxHeight="250">
<xctk:BusyIndicator IsBusy="True"
HorizontalAlignment="Center"
VerticalAlignment="Center"></xctk:BusyIndicator>
</Window>
The problem is because BusyIndicator was not designed to use it in separate window
The BusyIndicator is a ContentControl. What this means is that the BusyIndicator can contain a single child element within it?s open and closing tags.
Additionally if you do, first thing that is shown is small ui control (12x12 pixels) and after some latency finally the progress bar/busy indicator is shown.
By specifying SizeToContent='WidthAndHeight', xaml automatically resizes height and width relative to content. In this case (12x12) ui control is taken, and after some latency time finally as mentioned above busy indicator is shown. But by that time, the xaml ui renderer already applied SizeToContent and therefore you would have to manually re-position the progress bar.
I'm not really sure how xaml ui renderes works without specifying SizeToContent, but apparently it re-positions the busy indicator correctly after it is shown.

How to properly handle focus

Lets say I have next layout:
Window
UserControl
UserControl
UserControl
Button
GridControl
GridCell
And lets say that GridCell currently has Keyboard focus. If a user clicks on button. a message is displayed to user to confirm action. No matter of what choice the user selected (Yes or No), a focus should return to a CurrentCell on GridControl. By default, after a user selected some option, a focus would return to Window (reported by Snoop). I would assume that a Button that was clicked would retain focus, but apparently not.
Handling of button Command is done in ViewModel (MVVM).
How do I return keyboard focus to a current cell in grid?
You can probably pretty safely work around this problem by setting FocusManager.IsFocusScope="true" on your button or if there are multiple buttons the parent element they are in (eg StackPanel or whatever).
There are a few potential issues with this if you are using RoutedCommands. Basically RoutedCommands don't always work the way you expect them to inside of focus scopes. It sounds like you are binding directly to a command on the View Model though so that shouldn't be a problem. If you would like to read more about the RoutedCommand issue check this code project article out.
Here is what my sample code to verify this works looks like for your reference.
XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid Margin="25">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<!--You could also have the FocusManager.IsFocusScope set on the Border instead-->
<Border Margin="0,0,0,15">
<Button FocusManager.IsFocusScope="True" Click="ButtonBase_OnClick">Click me!</Button>
</Border>
<TextBox Grid.Row="1" x:Name="MessageTextBox"></TextBox>
</Grid>
</Window>
C#:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
MessageBox.Show("Clicked, message: " + MessageTextBox.Text);
}
}

WPF window not minimizing/maximizing

I am a novice WPF programmer. My problem is as below.
I have a WPF application and on the home screen, when I click on the maximize button, it does not maximize the screen, instead repositions it to the top left column. If I increase/decrease the screen size through click and drag, the maximize button works just fine. The window properties are set up as follows:
<Window x:Class="MyApp.Home"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
x:Uid="Window_Main"
x:Name="HomeWindow"
WindowStyle="None"
AllowsTransparency="True"
WindowStartupLocation="CenterScreen"
Margin="0"
BorderBrush="Transparent"
BorderThickness="0"
Title="Home"
MinWidth="1000" MinHeight="800"
ResizeMode="CanResizeWithGrip"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
SizeToContent="WidthAndHeight"
Visibility="Visible"
d:DesignHeight="1080" d:DesignWidth="1200">
The XAML for button is:
<Button x:Uid="btnRestore" x:Name="btnRestore" Height="20" Width="20" Style="{DynamicResource Control_WindowControlBoxStyle}" Margin="5,0,0,0" ToolTip="Toggle Restore" Click="btnRestore_Click" />
And the code for btnRestore_Click is simple:
private void btnRestore_Click(object sender, RoutedEventArgs e)
{
WindowState = WindowState.Maximized;
}
I am sure there must be some silly mistake that I am committing but not able to figure out what that is. Seems simple but caught me in spin. Any help would be appreciated.
You have SizeToContent="WidthAndHeight", which will make the window resize to whatever size the content in the Window is.
Either remove this property, or make sure first child of your Window tag doesn't have a size set

Window that is supposed to be fullscreen in WPF touchscreen application is moving when inner listbox is scrolled

I am writing a GUI application to run on a touchscreen device using VB.NET and WPF--it must be full screen at all times, like a kiosk app; the window must not be able to resize or move in any way. The window contains a ListBox that users can currently scroll through by dragging across the list. The problem I'm seeing is that when the user drags across the list, the whole window moves a bit, exposing the desktop underneath, then springs back into place once the user stops dragging. I have not been able to figure out how to keep the window stationary while still allowing users to drag across the ListBox to view all list items. Here is a somewhat simplified version of my code:
<Window
x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
WindowStyle="None"
WindowState="Maximized"
WindowStartupLocation="CenterScreen"
KeyboardNavigation.TabNavigation="None"
Topmost="True"
Focusable="False"
ResizeMode="NoResize"
ShowInTaskbar="False"
MaxHeight="1080px"
MaxWidth="1920px">
<Grid>
<ListBox
x:Name="docList"
ScrollViewer.HorizontalScrollBarVisibility="Hidden"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
BorderThickness="0">
<TextBlock Text="Item1" />
<TextBlock Text="Item2" />
<TextBlock Text="Item3" />
<TextBlock Text="Item4" />
<TextBlock Text="Item5" />
<TextBlock Text="Item6" />
</ListBox>
</Grid>
</Window>
I believe that if you handle the OnManipulationBoundaryFeedback(object sender, TouchEventArgs e) event on the listbox, and set the e.Handled property true, that should prevent the "bounce" of the application window.
It may also be possible (I hadn't thought of it until just now) to handle the event at the Window level, since it is a bubbling event, to mitigate the chance of any other controls causing the same behaviour.

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