Making PART of a WPF window click-through, but not its controls - wpf

In order to achieve a dropshadow effect, my window is slighty bigger than its main content with a transparent "border" around it. I am curious if there's a possibility to make this invisible border (coloured part in image) click-through only and prevent main content from being click-through.
This thread explains what to do in order to make the whole window click-through:
Making a WPF window click-through, but not its controls
Is there any way to adapt this approach for what I intend do achieve?

Only a window with a fully transparent background is really click through. For a semi-transparent window you could for example minimize the window yourself when clicking on the shadow, e.g.:
private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.OriginalSource == outer)
WindowState = WindowState.Minimized;
}
XAML:
<Window x:Class="WpfApp1.MainWindow"
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"
mc:Ignorable="d"
Title="MainWindow" Height="300" Width="300"
AllowsTransparency="True" WindowStyle="None">
<Window.Background>
<SolidColorBrush Color="Red" Opacity="0.3" />
</Window.Background>
<Grid x:Name="outer" Background="Transparent" MouseLeftButtonDown="Grid_MouseLeftButtonDown">
<Grid Background="Silver" Margin="10">
<TextBlock>GUI</TextBlock>
</Grid>
</Grid>
</Window>

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 set the position of StackPanel same as position of mouse pointer after click

I have Stack Panel in WPF application of height = 200, width = 200.
Its invisible by default.
I want to make stack panel visible on left click and want to set its
position same as mouse pointer.
Can anybody tell me how to do that. Thank you :)
You could make it visible by handling the MouseLeftButtonDown event and set the Visibility of the StackPanel to Visible. For you to be able to explicitly position it using coordinates you could put it in a Canvas and handle the MouseLeftButtonDown event for the Canvas. Please refer to the following sample code.
<Window x:Class="WpfApplication1.MainWindow"
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:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="700" Width="700">
<Canvas x:Name="canvas" Background="Transparent" MouseLeftButtonDown="Canvas_MouseLeftButtonDown">
<StackPanel x:Name="sp" Background="Yellow" Width="200" Height="200" Visibility="Hidden" />
</Canvas>
</Window>
private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Point point = e.GetPosition(canvas);
Canvas.SetLeft(sp, point.X - sp.Width / 2);
Canvas.SetTop(sp, point.Y - sp.Height / 2);
sp.Visibility = Visibility.Visible;
}

How to remove white strip on top of WPF window with WindowStyle=None?

Is it possible to remove the white strip on top of WPF window with Window Style=None. XAML and Window is shown in the screenshot:
What you are seeing in white is the re-size border. You can remove that and still make the window resizable by setting ResizeMode="CanResizeWithGrip" AllowsTransparency="True"
If you dont want to resize at all then do this - ResizeMode="NoResize", again you wont see the border but you cant resize.
<Window x:Class="HandsOnSolution.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" Background="Green" WindowStyle="None" ResizeMode="CanResizeWithGrip" AllowsTransparency="True">
<Grid>
</Grid>
</Window>
Edit
Good point by #devuxer, if you are interested in dragging you can add this piece of code to the window mouse down event
<Window MouseLeftButtonDown="Window_MouseLeftButtonDown"/>
//code behind
private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DragMove();
}
I had been hunting for a solution for a couple of days now, in simple words this link held the answer to my queries
though the code snippet that did the magic was:
<Setter Property="WindowChrome.WindowChrome">
<Setter.Value>
<WindowChrome CaptionHeight="0"
CornerRadius="2"
GlassFrameThickness="0"
NonClientFrameEdges="None"
ResizeBorderThickness="3"/>
</Setter.Value>
</Setter>
I just added the above property setter to the custom Window Style.
Hope that helped :)
A much simplified code, acting on only one property:
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="0"/>
</WindowChrome.WindowChrome>
I added this piece of code:
<WindowChrome.WindowChrome>
<WindowChrome GlassFrameThickness="0,0,0,1" CornerRadius="0" />
</WindowChrome.WindowChrome>
inside <Window> paste here <Window/> and it helped :)

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

Why doesn't WPF Canvas alow drop?

I have the following XAML for the main window:
<Window x:Class="ImageViewer.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="398" Width="434">
<Grid>
<Canvas AllowDrop="True" />
</Grid>
</Window>
But when I try to drag a file to the window, drop is not allowed. When Canvas is changed to ListBox, everything works perfectly.
How can the code be changed to allow drop to canvas?
By default, Canvas has no background so hit-testing is not picking up that the cursor is over the Canvas element, but is instead bubbling up to the Grid or Window which don't allow drop. Set the background to Transparent as follows and it should work:
<Window x:Class="ImageViewer.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="398" Width="434">
<Grid>
<Canvas AllowDrop="True" Background="Transparent" />
</Grid>
</Window>
This works like a charm! In code you would want to do something such as:
Canvas myCanvas = new Canvas();
myCanvas.AllowDrop = true;
myCanvas.Background = System.Windows.Media.Brushes.Transparent;

Resources