I would like to create an application with two or three screens for pc with tactile screen by using c# and WPF.
I would like to be able to navigate through the windows of my application by sliding the finger across the screen (left to right for previous screen or right to left for next screen).
How to proceed with c# and wpf ? What are the controls to use ? MatrixTransform and Manipulation events ? Scrollviewer ?
How to make the different windows of the application attached while gliding ? I mean: for right to left slide operation, we begin to see the next window while the current window disappears step by step.
My answer takes into account your additional comments, especially this one "There will be only two or three windows and each window keeps its fix relative position.". It suggests that you actually don't need windows. It'll be sufficient and much more easier to use custom user controls. These controls should placed next to each other. You can achieve it by using StackPanel with the horizontal orientation. This StackPanel should be inside ScrollViever which will provide scrolling. Additionally, ScrollViewer has PanningMode property which controls how it will cooperate with touch screens. Here is an example showing an idea:
<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"
Height="600"
Width="800">
<ScrollViewer HorizontalScrollBarVisibility="Hidden" PanningMode="HorizontalOnly">
<StackPanel Orientation="Horizontal">
<UserControl Width="500" Height="500" Background="Red" />
<UserControl Width="500" Height="500" Background="Blue" />
<UserControl Width="500" Height="500" Background="Yellow" />
</StackPanel>
</ScrollViewer>
</Window>
Related
I have included a MapControl in my WPF Core application using these instructions. I can correctly display the map but the problem is when I try to place any other interface element on top of the map. I have tried many ways but the map always overlays any other element I place on top of it, and therefore does not display. For example:
<Window x:Class="WpfMapControl.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:WpfMapControl"
xmlns:controls="clr-namespace:Microsoft.Toolkit.Wpf.UI.Controls;assembly=Microsoft.Toolkit.Wpf.UI.Controls"
mc:Ignorable="d"
Title="MainWindow" Height="400" Width="400">
<Grid>
<controls:MapControl Grid.Column="1"
x:Name="mapControl"/>
<Rectangle Width="100" Height="100" Fill="Red"></Rectangle>
</Grid>
This should look like this:
But the result is this:
How can I place any other element on top of the MapControl?
How can I place any other element on top of the MapControl?
Short answer: You can't.
Just like a Windows Forms control in a WindowsFormsHost, a WindowsXamlHost is hosted in a separate HWND that is always drawn on top of the WPF elements.
From the docs:
A hosted Windows Forms control is drawn in a separate HWND, so it is always drawn on top of WPF elements.
I'm trying to add a couple of things (a logo on the left and tab control items in the center) to a window chrome using the WindowChrome class. I'd like to keep the normal Win10 buttons, however, just like Google Chrome and similar applications do. Does anyone have any suggestions?
By default, WindowChrome does not hide the caption buttons, but it expands the client area to the entire window frame, so you need to make sure that there's nothing drawn on top of these buttons, such as the window's own background. This could be achieved by setting the background brush to {x:Null}, and also expanding the "glass" to the entire frame by setting it to -1 in order to avoid black (non-drawn) areas behind your controls.
You should also set WindowChrome.IsHitTestVisibleInChrome to True for the tab items (or any control in the non-client area) to make them interactive.
Here's an example:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="200"
Background="{x:Null}">
<WindowChrome.WindowChrome>
<WindowChrome GlassFrameThickness="-1" />
</WindowChrome.WindowChrome>
<TabControl Margin="{x:Static SystemParameters.WindowResizeBorderThickness}">
<TabItem WindowChrome.IsHitTestVisibleInChrome="True"
Height="{x:Static SystemParameters.WindowCaptionHeight}"
Header="TabItem" />
</TabControl>
</Window>
And here's what you'll get:
I have a WPF window declared like this
<Window 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="MyWindow"
Height="800" Width="200"
BorderThickness="0"
WindowStyle="None"
AllowsTransparency="False"
ResizeMode="CanResizeWithGrip"
Topmost="True"
Background="#fff59d"
ShowInTaskbar="False">
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="0" ResizeBorderThickness="5" />
</WindowChrome.WindowChrome>
</Window>
In this window there are a bunch of aligned buttons, making the window a nice tool bar that sits on top of the other windows.
Now I'd like to snap it to a screen edge (bottom, left, top, right) so that the working area of the screen is reduced by the window's area. Just like what happens with the Windows taskbar: the area covered by the taskbar is not used when other windows are maximized and the taskbar is always on top.
Any help is much appreciated !
EDIT
I'm adding an image to better explain my question:
I'm interested in position my WPF window on an edge so that the area of the window is forbidden to other windows.
First use Top="0" Left="0" to snap your "nice tool bar window" to the top and left edges of the screen. Second use the event Window_Loaded to set the window height equal to the screen height minus the taskbar height so that it will not be on top of it.
Side note Title doesn't make sens in your case
XAML:
<Window
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"
Width="200"
BorderThickness="0"
WindowStyle="None"
AllowsTransparency="False"
ResizeMode="CanResizeWithGrip"
Topmost="True"
Top="0"
Left="0"
Loaded="Window_Loaded"
Background="#fff59d"
ShowInTaskbar="False">
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="0" ResizeBorderThickness="5"/>
</WindowChrome.WindowChrome>
</Window>
Code-Behind:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
double TaskBarHeight = SystemParameters.PrimaryScreenHeight - SystemParameters.WorkArea.Height;
Height = SystemParameters.PrimaryScreenHeight - TaskBarHeight;
}
Edit
As #Bradley_Uffner explained in his comment you need an AppBar, you may want to take a look at Github.WpfAppBar or better check your options in this answer C# Window Docking.
You should check the "GridSplitter" control:
https://learn.microsoft.com/en-us/dotnet/framework/wpf/controls/how-to-resize-columns-with-a-gridsplitter
You should change your window(toolbar) to make it a UserControl so you can insert it in another window with GridSplitter on all edges (bottom, left, top, right). As for the "snap" part, I think you will have to handle the drag and drop event and hide/show the gridsplitters accordingly and either show/hide or add/remove the UserControl (your toolbar) behind the GridSplitter.
Sorry that I do not give much detail for the implementation, I believe there is quite a lot to do.
I would be very interested in another solution if someone knows a better way.
I know that the Telerik library(not free) provide a control for that https://docs.telerik.com/devtools/wpf/controls/raddocking/overview2
I have a WrapPanel inside a Window. In this case the controls inside the WrapPanel wrap when I manually resize the window.
However, the initial width is too much. I have put all controls in a horizontal wrap panel.
To make an initial width, I tried to set the Window to a width of 1000 (first try) and the wrappanel to 1000 (second try), but in this case the wrapping does not work anymore, only the 'border' (or padding) of the whole window is decreased or increased.
How can I change the width (and height) of the window in such a way that when I manually resize, the wrapping is taken into account.
Below a part of the XAML code:
Window x:Class="PcgTools.ListGenerator.ListGeneratorWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="{Binding ListGenerator, Source={StaticResource LocStrings}}" ResizeMode="CanResizeWithGrip"
Icon="/PcgTools;component/Gui/pcgtools.ico" Loaded="Window_Loaded" Closed="Window_Closed"
ShowInTaskbar="True" WindowStartupLocation="CenterOwner" SizeToContent="WidthAndHeight">
<WrapPanel Name="wrapPanel" Margin="4" Orientation="Horizontal">
I found the answer after trying myself a lot of combinations, but I added it to help other people:
<Window x:Class="PcgTools.ListGenerator.ListGeneratorWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="{Binding ListGenerator, Source={StaticResource LocStrings}}" ResizeMode="CanResizeWithGrip"
Icon="/PcgTools;component/Gui/pcgtools.ico" Loaded="Window_Loaded" Closed="Window_Closed"
ShowInTaskbar="True" WindowStartupLocation="CenterOwner"
Width="1000" SizeToContent="Height">
<WrapPanel Name="wrapPanel" Margin="4" Orientation="Horizontal">
The conclusion is:
Set the window Width in the window
Set the window SizeToContent to Height (only)
This isn't directly related to the original question, but others might find it helpful, if like I did, they see this as one of the first search results in google, and no other results were helpful.
If you're encountering this in a Grid, you may have that Grid in a ScrollViewer with HorizontalScrollBarVisibility="Auto". You need to set that to Disabled.
I'm new to WPF and am used to winforms. I don't understand why the compiled output is not the same as in the design view. I find this to be bit annoying and misleading.
When adding elements, I snapped them to the red border and the results are not consistent with what I see in the compiled window. In winforms, I'm used to using table layouts, panels, and docking and aligning items. Is there a proper way of doing this in WPF to get consistent results?
The XAML
<Window x:Class="WpfApplication4.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>
<Rectangle Fill="#FFF4F4F5" HorizontalAlignment="Left" Height="300" Margin="10,10,0,0" Stroke="Black" VerticalAlignment="Top" Width="497"/>
</Grid>
</Window>
In WPF most containers don't have the notion of children position. Instead, most controls use properties such as Margin, HorizontalAlignment and VerticalAlignment to define their layout. Furthermore, specific containers offer different functions. If you want docking, you can use a DockPanel. If you want stacked elements, you can use a StackPanel and so on. I suggest you to look up a few tutorials online, it's plenty of resources.
In your case, if you want your control to completely fill its container, remove the Margin, VerticalAlignment, HorizontalAlignment, Width and Height attributes from its XAML code.