Load two windows on two separate screens - c#

I am trying to create a WPF presentation application where the Primary Window on the Primary Screen will be used to update the content on the Presentation Window, which needs to be on the secondary screen. I am looking for samples or code snippet that can help me do that.
Also I have attempted the following and doesn't work:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var screens = System.Windows.Forms.Screen.AllScreens;
if (screens.Length > 1)
{
var window = new MainWindow
{
WindowStartupLocation = WindowStartupLocation.Manual,
WindowState = WindowState.Maximized,
Top = screens[0].WorkingArea.Top,
Left = screens[0].WorkingArea.Left,
Topmost = true
};
window.Show();
var pesentationWindow = new PresentationWindow
{
WindowStartupLocation = WindowStartupLocation.Manual,
ShowInTaskbar = false,
Top = screens[1].WorkingArea.Top,
Left = screens[1].WorkingArea.Left,
Topmost = true
};
pesentationWindow.Show();
}
}

You can use Screen object in this way
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Window1 w1 = new Window1();
Window2 w2 = new Window2();
Screen s1 = Screen.AllScreens[0];
Screen s2 = Screen.AllScreens[1];
Rectangle r1 = s1.WorkingArea;
Rectangle r2 = s2.WorkingArea;
w1.Top = r1.Top;
w1.Left = r1.Left;
w2.Top = r2.Top;
w2.Left = r2.Left;
w1.Show();
w2.Show();
w2.Owner = w1;
}
Follow this link for more details.

Using the System.Windows.Forms.Screen.AllScreens static property you can figure out how many screens there are and what their resolutions are. Figure out which is the PrimaryScreen and set the secondary Window to the correct size and position. See for more info: Trouble creating a WPF window in a secondary monitor
Then simply create two separate Window classes that bind your DataContext's bindings differently. For Example:
class DataContext
{
public string Header { get; set; }
}
<Window Title="Primary Window">
<TextBox Text="{Binding Header}"/>
</Window>
<Window Title="Presentation Window">
<TextBlock Content="{Binding Header}"/>
</Window>

Related

How can I navigate between views/screens by dragging sideways (swipe gesture)?

So I want the user to change the displayed window by dragging it sideways. It shouldn't matter where exactly on the screen is his cursor (so only the dragging action matter) I draw a little representation of what I have in mind. I want the user to see the 2nd screen coming after the cursor, even retracting when he moves his cursor back to the right (basically following his cursor). This action should be both ways: from main window to 2nd window AND from 2nd window back to main window
How would you approach this?
EDIT:
Picture 1; The user places his cursor on point A and clicks. While holding click he drags it across the green arrow.
Picture2; This picture represents and intermediate state when the "slide" is still in progress (you can see the "Statistics" screen still hasn't fully taken over the initial screen)
Picture3; Represents the final state; after the user got at the end of the (imaginary) green arrow. The Statistics screen is now fully displayed and the user can read the information that is on it.
The opposite of what happened now should be allowed (dragging from left to right in order to go back to the initial screen)
You need to apply a translate transform to your content.
The following example shows how to drag the content (or the image of the content). For simplicity, the example only shows how to swipe from right to left. It also doesn't show how to implement a history to navigate back. You would need a Queue to store the next pages and a Stack for the previous pages (based on the swipe direction).
Although the below example does it, I don't recommend to use controls directly to handle pages and their navigation. Instead create page data models and render the controls using a DataTemplate for each page model.
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public object CurrentPage
{
get => (object)GetValue(CurrentPageProperty);
set => SetValue(CurrentPageProperty, value);
}
public static readonly DependencyProperty CurrentPageProperty = DependencyProperty.Register(
"CurrentPage",
typeof(object),
typeof(MainWindow),
new PropertyMetadata(default));
private StackPanel DraggableContent { get; }
// Accept swipe after 25% swipe delta
// based on the max possible swipe width (a displayed page).
// Note that the 'PageHost' will host two pages (their image)
// during the swipe action.
private double SwipeAcceptDragThreshold
=> this.PageHost.ActualWidth / 2 * 0.25;
private bool IsSwiping { get; set; }
private double HorizontalDragStart { get; set; }
private UserControl PreviousPage { get; set; }
private UserControl NextPage { get; set; }
/* Page controls */
private UserControl GreenPage { get; }
private UserControl OrangePage { get; }
private UserControl BluePage { get; }
public MainWindow()
{
InitializeComponent();
this.GreenPage = new PageControl() { Background = Brushes.Green };
this.OrangePage = new PageControl() { Background = Brushes.Orange };
this.BluePage = new GreenPage() { Background = Brushes.Blue };
this.CurrentPage = this.GreenPage;
this.NextPage = this.OrangePage;
this.DraggableContent = new StackPanel() { Orientation = Orientation.Horizontal };
}
protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnPreviewMouseLeftButtonDown(e);
this.HorizontalDragStart = e.GetPosition(this).X;
}
protected override void OnPreviewMouseMove(MouseEventArgs e)
{
base.OnPreviewMouseMove(e);
if (e.LeftButton == MouseButtonState.Released)
{
return;
}
double dragDelta = e.GetPosition(this).X - this.HorizontalDragStart;
if (!this.IsSwiping)
{
bool isSwipeRightToLeft = dragDelta < HorizontalDragStart;
UserControl swipeInPage = null;
UserControl swipeOutPage = null;
if (isSwipeRightToLeft)
{
if (this.NextPage == null)
{
return;
}
swipeInPage = this.NextPage;
swipeOutPage = this.CurrentPage as UserControl;
this.PreviousPage = this.CurrentPage as UserControl;
}
this.IsSwiping = true;
/* Create an image of the content that will be dragged, using VisualBrush */
swipeInPage.Height = this.PageHost.ActualHeight;
swipeInPage.Width = this.PageHost.ActualWidth;
swipeOutPage.Height = this.PageHost.ActualHeight;
swipeOutPage.Width = this.PageHost.ActualWidth;
this.CurrentPage = null;
// Prepare the snapshot
this.DraggableContent.Children.Add(swipeOutPage);
this.DraggableContent.Children.Add(swipeInPage);
// To improve performance, the user will only drag a snapshot
// of the pages. The snapshot is painted on an empty Grid
// using a VisualBrush.
this.CurrentPage = new Grid()
{
Background = new VisualBrush(DraggableContent),
Width = this.PageHost.ActualWidth * 2 // Host two pages
};
}
this.TranslateTransform.X = dragDelta;
}
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonUp(e);
if (this.IsSwiping)
{
this.IsSwiping = false;
double dragDelta = Math.Abs(e.GetPosition(this).X - this.HorizontalDragStart);
bool isDragAccepted = dragDelta > this.SwipeAcceptDragThreshold;
// Disconnect page controls from the visual tree
this.DraggableContent.Children.Clear();
this.CurrentPage = isDragAccepted
? NextPage
: this.PreviousPage;
this.TranslateTransform.X = 0;
// TODO::Generate and set next page or null if last page reached
this.NextPage = this.BluePage;
}
}
}
MainWindow.xaml
<Window>
<!-- Allow content to exceed the Window -->
<ScrollViewer HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden">
<ContentPresenter x:Name="PageHost"
Content="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=CurrentPage}">
<ContentPresenter.RenderTransform>
<TranslateTransform x:Name="TranslateTransform" />
</ContentPresenter.RenderTransform>
</ContentPresenter>
</ScrollViewer>
</Window>
PageControl.xaml
<UserControl>
<Grid Background="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=Background}" />
</UserControl>

Why is the TitleBar title gone after adding acrylic effect?

I used the following code in MainPage.xaml.cs to add acrylic effect on the TitleBar
public void AcrylicTitleBar()
{
CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;
var title = ApplicationView.GetForCurrentView();
title.TitleBar.ButtonBackgroundColor = Colors.Transparent;
title.TitleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
title.TitleBar.ButtonForegroundColor = (Color)Resources["SystemBaseHighColor"];
}
but I don't know why the TitleBar title is gone.
If I remove the above code the TitleBar title comes back. can someone please help me?
Your code is not applying any "Acrylic" effect to your app Title bar .
It is simply setting the button background color to "Transparent" which is no where close to the acrylic.
In order to have an acrylic title bar you need to do the following :
In your MainPage.xaml.cs , add code for hiding the default title bar and update its layout so that it still works like the default toolbar :
public MainPage()
{
// Hide default title bar.
var coreTitleBar = CoreApplication.GetCurrentView().TitleBar;
coreTitleBar.ExtendViewIntoTitleBar = true;
UpdateTitleBarLayout(coreTitleBar);
}
private void UpdateTitleBarLayout(CoreApplicationViewTitleBar coreTitleBar)
{
// Get the size of the caption controls area and back button
// (returned in logical pixels), and move your content around as necessary.
LeftPaddingColumn.Width = new GridLength(coreTitleBar.SystemOverlayLeftInset);
RightPaddingColumn.Width = new GridLength(coreTitleBar.SystemOverlayRightInset);
TitleBarButton.Margin = new Thickness(0, 0, coreTitleBar.SystemOverlayRightInset, 0);
// Update title bar control size as needed to account for system size changes.
AppTitleBar.Height = coreTitleBar.Height;
}
private void CoreTitleBar_LayoutMetricsChanged(CoreApplicationViewTitleBar sender, object args)
{
UpdateTitleBarLayout(sender);
}
Next , in your MainPage.xaml add AcrylicBrush as the main or parent grid background (Note : that this grid should wrap all the contents in the page ):
<Grid>
<Grid.Background>
<AcrylicBrush BackgroundSource="HostBackdrop"
TintColor="{ThemeResource SystemAltHighColor}"
FallbackColor="{ThemeResource SystemAltHighColor}"
TintOpacity="0.5">
</AcrylicBrush>
</Grid.Background>
</Grid>
Hope this helps!

WPF - Incorrect Window resolution after setting Window.Windowstate to Maximized programmatically

So I'm trying to open a maximized Window on my secondary monitor. It all works fine, except it's height is 2 pixels lower than it should be.
My secondary monitor has a resolution of 1280x1024. However once I inspect the window, it's 1280x1022. Does anyone know the problem?
OS: Windows 10
Actual height/width image (Puush)
Here is some code:
SecondaryMonitorWindow smw = new SecondaryMonitorWindow();
smw.Show();
XAML
Loaded="OnWindowLoaded"
WindowStartupLocation="Manual"
WindowStyle="None"
SnapsToDevicePixels="True"
Height="1280"
Width="1024"
Constructor
public SecondaryMonitorWindow()
{
InitializeComponent();
Instance = this;
}
Event
private void OnWindowLoaded(object sender, RoutedEventArgs e)
{
this.MaximizeToSecondaryMonitor();
}
ExtensionMethod
public static void MaximizeToSecondaryMonitor(this Window window)
{
var secondaryScreen = Windows.Forms.Screen.AllScreens.Where(s => !s.Primary).FirstOrDefault();
if (secondaryScreen != null)
{
if (!window.IsLoaded)
window.WindowStartupLocation = WindowStartupLocation.Manual;
window.Left = secondaryScreen.WorkingArea.Left;
window.Top = secondaryScreen.WorkingArea.Top;
window.Width = secondaryScreen.WorkingArea.Width;
window.Height = secondaryScreen.WorkingArea.Height;
if (window.IsLoaded)
window.WindowState = WindowState.Maximized;
}
}
Try setting the parameter grammatically, this way only you'll be able to achieve the perfect size :
public MainWindow()
{
InitializeComponent();
this.Height = SystemParameters.WorkArea.Height;
this.Width = SystemParameters.WorkArea.Width;
}
however there are bugs around Window 10. if you are using please let me know I'll update the answer.
For Window 10 this post will help. there are no design Border in window 10 so there is some pixel problem. I'm not sure what is Window decoration settings on your OS, but try this.
this.Height = SystemParameters.WorkArea.Height + SystemParameters.FixedFrameHorizontalBorderHeight;
this.Width = SystemParameters.WorkArea.Width + SystemParameters.FixedFrameVerticalBorderWidth;
If there were some other borders are removed try ResizeFrame border size addition too.

Set WindowStartupLocation to the Margin.Top of Button1 of the main window

I'm working on a project where I have to add a small preview pane and a about box whenever a user is hovering the buttons on the main window.
For the examlpe: I have a window - preview.xaml, and my main window called MainWindow.xaml.
How do I set the preview windows bottom to appear on the top of button1 on the MainWindow?
I tried something like this without any luck:
public preview()
{
InitializeComponent();
this.WindowStartupLocation = WindowStartupLocation.Manual;
Top = mainWindow.button1.Margin.Top;
}
I hope my ramblings makes any sense...
Any help is greatly appreciated!
You need to set Left and Top window properties to screen coordinates, button margins won't help here. Use PointToScreen function to obtain screen coordinates of your buttons:
private void button1_MouseEnter(object sender, MouseEventArgs e)
{
var control = ((FrameworkElement)sender);
// get screen coordinates of (0,0) point of button
var location = control.PointToScreen(new Point(0, 0));
var w = new preview()
{
WindowStartupLocation = System.Windows.WindowStartupLocation.Manual,
ShowActivated = false,
};
w.Top = location.Y - w.Height;
w.Left = location.X + (control.ActualWidth - w.Width) / 2;
w.Show();
}
You have to do it the other way round. In your MainWindow where you open the preview-window do something like this:
PreviewWindow preview = new PreviewWindow
{
Owner = this,
WindowStartupLocation = WindowStartupLocation.Manual,
Top = button1.Margin.Top
};
preview.Show();
If you want to reuse that window, you have to do a little logic around.

How do you display a custom UserControl as a dialog?

How do you display a custom UserControl as a dialog in C#/WPF (.NET 3.5)?
Place it in a Window and call Window.ShowDialog.
(Also, add references to: PresentationCore, WindowsBase and PresentationFramework if you have not already done so.)
private void Button1_Click(object sender, EventArgs e)
{
Window window = new Window
{
Title = "My User Control Dialog",
Content = new MyUserControl()
};
window.ShowDialog();
}
Window window = new Window
{
Title = "My User Control Dialog",
Content = new OpenDialog(),
SizeToContent = SizeToContent.WidthAndHeight,
ResizeMode = ResizeMode.NoResize
};
window.ShowDialog();
Has worked like a magic for me.
Can it be made as a modal dialog?
Ans : ShowDialog it self make it as Modal Dialog.. ...
As far as I know you can't do that. If you want to show it in a dialog, that's perfectly fine, just create a new Window that only contains your UserControl, and call ShowDialog() after you create an instance of that Window.
EDIT:
The UserControl class doesn't contain a method ShowDialog, so what you're trying to do is in fact not possible.
This, however, is:
private void Button_Click(object sender, RoutedEventArgs e){
new ContainerWindow().ShowDialog();
}
namespace System.Window.Form
{
public static class Ext
{
public static DialogResult ShowDialog(this UserControl #this, string title)
{
Window wind = new Window() { Title = title, Content = #this };
return wind.ShowDialog();
}
}
}
The use of it maybe as simple as UserControlInstance.ShowDialog().
A better customized implementation would be by extending the Window class and customizing it using the the designer and code to get any functionality.
I know this is for .net 3.5, but here is a workable solution for .net 2.0
MyUserControl myUserControl= new MyUserControl();
Form window = new Form
{
Text = "My User Control",
TopLevel = true,
FormBorderStyle = FormBorderStyle.Fixed3D, //Disables user resizing
MaximizeBox = false,
MinimizeBox = false,
ClientSize = myUserControl.Size //size the form to fit the content
};
window.Controls.Add(myUserControl);
myUserControl.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
window.ShowDialog();
You can also use MaterialDesignThemes.Wpf (downloadable on NuGet, .NET 4.5+). Then you can simply do:
{
var view = new YourUserControl();
var result = await DialogHost.Show(view, "RootDialog", ClosingEventHandler);
}
private void ClosingEventHandler(object sender, DialogClosingEventArgs eventArgs)
{ } //Handle Closing here
If the answer by 'sixlettervariables' is modified as so, it works
private void button1_Click ( object sender, RoutedEventArgs e )
{
Window window = new Window
{
Title = "My User Control Dialog",
Content = new UserControl ( ),
Height = 200, // just added to have a smaller control (Window)
Width = 240
};
window.ShowDialog ( );
}

Categories

Resources