WPF Mirror grid content in different window - c#

I am developing a WPF softare.
At a Main Window, I have a grid named "gridWindow" and a few buttons.
Each button click event will actually calls up different windows respectively and then grab the content in the window and add into the grid in Main Window.
private void btnWelcome_Click(object sender, RoutedEventArgs e)
{
Window_Welcome childWindow = new Window_Welcome();
object PrjWindowContent = childWindow.Content;
childWindow.Content = null;
gridWindow.Children.Add(childWindow as UIElement);
}
Then I have another button which will need to open a new window named "BlackScreen" and mirror everything in the Main Window's grid.
The content inside the grid in MainWindow is always changing based on the system time or user input from others MainWindow's controls. The mirroring window's content will need to change accordingly too.
I learnt that I might need a visual brush to duplicate the screen.
But I just failed to do so.
This is my code in the BlackScreen.xaml.
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="Black">
<Viewbox Name="vbox" Stretch="Uniform"><!--DataContext="{Binding ElementName=gridWindow}"-->
<Grid>
<Grid.Background>
<VisualBrush Stretch="Uniform" Visual="{Binding}">
</VisualBrush>
</Grid.Background>
</Grid>
</Viewbox>
</Grid>
</Grid>

Here is a simple example of how you could use the VisualBrush to 'mirror' your main content Grid (or any other section of your UI):
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid Name="MainContent">
<Ellipse Fill="Red" />
<Rectangle Fill="Yellow" Margin="50" />
</Grid>
<Rectangle Grid.Row="1">
<Rectangle.Fill>
<VisualBrush Visual="{Binding ElementName=MainContent}" />
</Rectangle.Fill>
</Rectangle>
</Grid>
This produces the following:

Related

Hiding/Showing a UserControl WPF

I am building a WPF MVVM application.
What I have:
I have a ShellWindow which looks like this:
It is composed by 2 rows:
1: the hamburger menu (not important) with Height="*"
2: the console with Height="100"
The console is a UserControl:
<UserControl
//namespaces>
<Grid Name="LoggingGrid" Background="Black">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Margin="{StaticResource SmallLeftMargin}">
<Button
x:Name="CollapseBtn"
Width="25"
Height="25"
Click="CollapseBtn_Click"
Content="▲">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Ellipse Fill="White" />
<ContentPresenter
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Content}" />
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
<StackPanel Margin="5,0,0,0" Orientation="Horizontal">
<Image
Height="25"
Source="/Images/console-icon.png"
Visibility="Visible" />
<Label
Content="Console"
FontSize="16"
Foreground="White" />
</StackPanel>
</TextBlock>
<Border Grid.Row="1">
<ListView
x:Name="LoggingList"
Margin="5"
Background="Black"
BorderThickness="0"
Foreground="White"
ItemsSource="{Binding Logs, UpdateSourceTrigger=PropertyChanged}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto" />
</Border>
</Grid>
</UserControl>
I have omitted the non-important things.
What I want to do:
Whenever the user clicks on the button, the console should collapse and look something like this:
The arrow is also changed.
How can I implement this? What is the best approach using MVVM?
What I have tried:
I have tried using a button click event handler in the code behind - CollapseBtn_Click, just to see what will happen:
private void CollapseBtn_Click(object sender, System.Windows.RoutedEventArgs e)
{
LoggingGrid.Visibility = System.Windows.Visibility.Hidden;
}
Apparently it removes the user control and leaves a white background where it used to be.
Instead of setting the Visibility of the whole LoggingGrid to Hidden, you should set the Visibility of the LoggingList to Collapsed. (For the difference between Hidden and Collapsed, see here: Difference between Visibility.Collapsed and Visibility.Hidden).
Depending on your layout in the ShellWindow you probably have to adjust your row height configuration in the UserControl such that the collapsed LoggingGrid leads to a row with a height of zero.
Regarding MVVM the best approach would be to bind the Button to a bool property ConsoleVisible on your ViewModel such that clicking the button toggles the property between true and false. The styling of the button can be bound to the same property. For the LoggingList Visibility you could use a Binding with a BooleanToVisibilityConverter on the same property.

WPF Popup as a separate control written in xaml

Is there chance to create a WPF Popup as a separate control, so it is not inside a window or user control?
I have a popup written in XAML:
<Popup PopupAnimation="Fade" Name="MyPopup" MinWidth="200" MinHeight="100" Width="200" Height="100" Placement="Center" VerticalAlignment="Center" HorizontalAlignment="Center" IsEnabled="True" IsOpen="False">
<Grid Width="Auto" Height="Auto" Background="Gray">
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border BorderThickness="2" CornerRadius="8" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.RowSpan="2">
<Border.BorderBrush>
<SolidColorBrush Color="Gray"/>
</Border.BorderBrush>
<Border.Background>
<SolidColorBrush Color="White"/>
</Border.Background>
</Border>
<StackPanel Grid.Row="0">
<Label Foreground="Blue" Content="Popup_Title"/>
</StackPanel>
<GroupBox Grid.Row="1" Header="Popup example content">
<StackPanel>
</StackPanel>
</GroupBox>
</Grid>
</Popup>
Now, on button click of my other control, I would like to do something like this:
private void Button_Click(object sender, RoutedEventArgs e)
{
PopupControl p = new PopupControl();
p.IsOpen = true;
}
By looking at the example of UserControl or Window, I understand that I need to connect this popup with the actual c# class, something like:
public partial class PopupControl : Popup
{
public PopupControl()
{
InitializeComponent();
}
}
and then inside the Popup's XAML add class:
x:Class="WpfApplication1.PopupControl".
but two things:
1) There is no such a thing as x:Class for PopUp
2) Deriving from Popup won't have InitializeComponent(); method.
You almost got it right. While copy-pasting your Popup code in its own XAML file, you didn't add the necessary x namespace that contains the attached property x:Class:
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
As soon as you add this to your root element (Popup), you can add x:Class="WpfApplication1.PopupControl". This will lead to the generation of a partial class in your obj folder that contains the InitializeComponent method that you were missing.
The easiest way to do that is by
creating a new UserControl from the "Add Item" dialog.
Then, rename the root element from UserControl to Popup.
Finally, from the code behind class, just remove : UserControl.

How can i give the print preview in WPF, for a complete window?

How to give print preview functionality for a complete window before it gets printed here is the code i have implemented for printing the complete window.
My Code Behind :
private void Canvas_Print_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
PrintDialog printdlg = new PrintDialog();
MainWindow win = new MainWindow();
this.Width = 350;
this.Background = Brushes.White;
panel.ScrollToTop();
panel.ScrollToLeftEnd();
win.Tag = this;
if (printdlg.ShowDialog() == true)
{
printdlg.PrintVisual(panel.Content as Visual, "MyApplication");
}
}
Here is a sample for print preview kind of functionality
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Viewbox>
<Border BorderBrush="Gray"
Background="White"
BorderThickness="2"
Margin=".2in">
<Rectangle Width="8.5in"
Height="11in"
Margin=".2in">
<Rectangle.Fill>
<VisualBrush Visual="{Binding ElementName=visualToPrint}"
Stretch="Uniform" />
</Rectangle.Fill>
</Rectangle>
<Border.Effect>
<DropShadowEffect Opacity=".25" />
</Border.Effect>
</Border>
</Viewbox>
<TextBox Text="change this text"
Grid.Row="1"
x:Name="visualToPrint" />
</Grid>
I created a rectangle of the size of a paper (assuming 8.5" 11") and set the fill to VisualBrush which is rendering my visual visualToPrint (panel in your case).
Also wrapped it into a border for page like effect and whole into a ViewBox to enable resizing
result
i chose a textbox for example you can choose any visual of your choice in the visual brush eg Visual="{Binding ElementName=panel}"

Autosizing button child elements as button changes size

I have a number of buttons within a grid, that all change size based on the application being resized. Some buttons have child elements such as an ellipse or rectangle. I can't seem to get these to resize as well.
Here is some code:
<Grid DockPanel.Dock="Right" Width="121">
<Grid.RowDefinitions>
<RowDefinition Height="121*" />
<RowDefinition Height="121*" />
// Snip
</Grid.RowDefinitions>
<Button Name="ellipseButton" PreviewMouseDown="EllipseButtonClickedEvent" HorizontalAlignment="Stretch" Grid.Row="0">
<Ellipse Width="90" Height="90" Stroke="Black"></Ellipse>
</Button>
// Snip
</Grid>
I know that the height and width of the ellipse is explicitly set, but when I remove that, I can't seem to get the ellipse to show at all.
I would appreciate any advice.
Thanks.
Just set the HorizontalContentAlignment and VerticalContentAlignment properties of the button to Stretch:
<Button Name="ellipseButton" PreviewMouseDown="EllipseButtonClickedEvent" HorizontalAlignment="Stretch" Grid.Row="0"
HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" >
<Ellipse Stroke="Black" />
</Button>

Button Click event from Resource Directory

i built a control template, with two buttons, which i use in the MainWindow Class:
The ControlTemplate:
<ControlTemplate x:Key="LeftPanelTemplate">
<Grid Grid.Column="0" Grid.Row="0" Margin="10,15,5,5" >
<Border BorderThickness="7" CornerRadius="4">
<Border.BorderBrush>
<SolidColorBrush Color="#73B2F5" Opacity="0.5"/>
</Border.BorderBrush>
<Grid>
<Grid.Background>
<SolidColorBrush Color="#73B2F5" Opacity="0.5"/>
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Button Name="CustomerButton" Grid.Row="1" Grid.Column="0" Width="40" Height="40" Content="Customer" Click="CustTabButton_Click" ></Button>
<Button Name="BossButton" Grid.Row="1" Width="40" Height="40" Content="Boss" Margin="23,206,23,114" Click="BossTabButton_Click"></Button>
</Grid>
</Border>
</Grid>
</ControlTemplate>
I reference it at the MainWindow XAML:
<ContentControl Template="{StaticResource LeftPanelTemplate}"/>
i get an error that the click events of the two buttons inside the control template could not be found - because i moved it to the ResourceDirectory file called MainWindowResources.xaml:
'MyWPFApp.MainWindowResource' does not contain a definition for
'CustTabButton_Click' and no extension method 'CustTabButton_Click'
accepting a first argument of type 'MyWPFApp.MainWindowResource' could
be found (are you missing a using directive or an assembly reference?)
i found this link: Is it possible to set code behind a resource dictionary in WPF for event handling?
is there a shorter way for the click events in the MainWindow code behind to be executed from the resource Directory? because moving the whole code from the MainWindow to a REsourceDirectory.xaml.code can take alot of time and expose to public alot of variables.
you could use commands instead of button click and bind the commands from your mainwindow to the usercontrol.

Categories

Resources