Mirror grid in xaml/wpf into another xaml/wpf - wpf

So basically I have a grid name 'gridSeatPlan' with buttons on it which allow the user to select. Is it possible for me to display the result that had been selected by the user into a second window which will be display on the second monitor?
I'm using code below but didn't get the mirror of the grid on the MainMenu. May I know which part did I done it wrong?
<Rectangle>
<Rectangle.Fill>
<VisualBrush Visual="{Binding ElementName=gridSeatPlan}"/>
</Rectangle.Fill>
</Rectangle>
This is the code I use to show the form for the second monitor
If dualScreenSeatPlan = 2 Then
Dim screen As Screen
screen = Screen.AllScreens(dualScreenSeatPlan - 1)
If Screen.AllScreens.Length > 1 Then
FormSeatPlanDual = New frmSeatPlan_DualMirror
BaseForm.ParentSeatPlanDual = FormSeatPlanDual
FormSeatPlanDual.StartPosition = FormStartPosition.Manual
FormSeatPlanDual.Location = screen.WorkingArea.Location
FormSeatPlanDual.TopMost = True
FormSeatPlanDual.Show()
End If
ElseIf dualScreenSeatPlan = 1 Then
Dim screen As Screen
screen = Screen.AllScreens(dualScreenSeatPlan - 1)
If Screen.AllScreens.Length > 1 Then
FormSeatPlanDual = New frmSeatPlan_DualMirror
BaseForm.ParentSeatPlanDual = FormSeatPlanDual
FormSeatPlanDual.StartPosition = FormStartPosition.Manual
FormSeatPlanDual.Location = Screen.PrimaryScreen.WorkingArea.Location
FormSeatPlanDual.TopMost = False
FormSeatPlanDual.Show()
End If

Related

VisualTreeHelper.GetDescendantBounds returns 'Empty' (Infinity)

In my WPF app I dynamically load a XAML drawing from XML at runtime. This drawing is a complex series of nested canvas and geometry 'Path's (for example):
<?xml version="1.0" encoding="utf-8"?>
<Canvas Width="1593" Height="1515">
<Canvas.Resources />
<Canvas>
<Path Fill="…" Data="…"/>
<Path Fill="…" Data="…"/>
<Path Fill="…" Data="…"/>
<Canvas>
<Canvas>
<Path Stroke="…" StrokeThickness="…" StrokeMiterLimit="…" StrokeLineJoin="…" StrokeEndLineCap="…" Data="…"/>
<Path Stroke="…" StrokeThickness="…" StrokeMiterLimit="…" StrokeLineJoin="…" StrokeEndLineCap="…" Data="…"/>
</Canvas>
</Canvas>
<Path Fill="…" Data="…"/>
<Path Fill="…" Data="…"/>
<Path Fill="…" Data="…"/>
</Canvas>
</Canvas>
The outer canvas' Height/Width are incorrectly set, as many of the Path expressions exceeds these dimensions. I don't have any control over this source XML, so I'm required to fix it up at runtime after the drawing is loaded. To load the drawing I use code similar to the following:
public static Canvas LoadDrawing(string xaml)
{
Canvas drawing = null;
using (var stringreader = new StringReader(xaml))
{
using (var xmlReader = new XmlTextReader(stringreader))
{
drawing = (Canvas)XamlReader.Load(xmlReader);
}
}
return drawing;
}
Then, I attempt to reset the canvas size, using the following code:
var canvas = LoadDrawing(…);
someContentControOnTheExistingPage.Content = canvas;
var bounds = VisualTreeHelper.GetDescendantBounds(canvas); // << 'bounds' is empty here.
canvas.Width = bounds.Width;
canvas.Height = bounds.Height;
Except, at the point where I create the canvas element, the bounds is empty. However, if I just wire a simple button and invoke GetDescendantBounds() interactively on the same canvas, then I receive expected height/width.
My takeaway is that GetDescendantBounds() does not work unless the layout with the new control has completed. So my questions are:
Is there a way I can force a layout computation prior to running GetDescendantBounds()? Or…
Is there another way I can get the bounds/extents of a visual tree, prior adding it to its parent?
Thanks
-John
Is there a way I can force a layout computation prior to running GetDescendantBounds?
Yes, call the Arrange and Measure methods of the Canvas:
var canvas = LoadDrawing("...");
someContentControOnTheExistingPage.Content = canvas;
canvas.Arrange(new Rect(someContentControOnTheExistingPage.RenderSize));
canvas.Measure(someContentControOnTheExistingPage.RenderSize);
var bounds = VisualTreeHelper.GetDescendantBounds(canvas);
canvas.Width = bounds.Width;
canvas.Height = bounds.Height;
First you need to add this line in your xaml string.
xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
This is C# code example to find control and properties.
public void LoadXaml()
{
string canvasString = #"<Canvas Name='canvas1' xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' Width = '1593' Height = '1515'> </Canvas>";
var canvas = LoadDrawing(canvasString);
//Use this line you will find height and width.
Canvas canvasCtrl = (Canvas)LogicalTreeHelper.FindLogicalNode(canvas, "canvas1");
// var bounds = VisualTreeHelper.GetDescendantBounds(canvas); // << 'bounds' is empty here.
canvas.Width = canvasCtrl.Width; //bounds.Width;
canvas.Height = canvasCtrl.Height; //bounds.Height;
}

Creating a Circular GUI

So one of my latest side projects is developing a application detection and populating assistant. Programmatically I am absolutely fine populating the backend code for what I want accomplished. But I've run into a road block on the GUI. I need a GUI that is a Quarter circle that extends from the task bar to the bottom right of a standard windows operating system. When the user doubleclicks on the application, the circle rotates into view. I can do this with a typical windows form that has a transparent background and a fancy background image. But the square properties of the form will still apply when the user has the application open. And I do not want to block the user from higher priority apps when the circle is open.
I'm not really stuck on any one specific programming language. Although, I would prefer that it not contain much 3d rendering as it is supposed to be a computing assistant and should not maintain heavy RAM/CPU consumption whilst the user is browsing around.
Secondarily, I would like the notches of the outer rings to be mobile and extend beyond the gui a mere centimeter or so.
I would not be here if I hadn't had scoured the internet for direction on this capability. But what I've found is application GUI's of this nature tend to be most used in mobile environments.
So my questions are: How can I accomplish this? What programming language can I write this in? Is this a capability currently available? Will I have to sacrifice user control for design?
I wrote out some code doing something close to what you described.
I’m not sure to understand how you do want the circle to appear, so I just let a part of it always visible.
And I didn’t get the part about the mobile outer ring.
Creating and placing the window
The XAML is very simple, it just needs a grid to host the circle’s pieces, and some attributes to remove window decorations and taskbar icon:
<Window x:Class="circle.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Circle"
Width="250"
Height="250"
AllowsTransparency="True"
Background="Transparent"
MouseDown="WindowClicked"
ShowInTaskbar="False"
WindowStyle="None">
<Grid Name="Container"/>
</Window>
To place the window in the bottom right corner, you can use SystemParameters.WorkArea in the constructor:
public MainWindow()
{
InitializeComponent();
var desktopDim = SystemParameters.WorkArea;
Left = desktopDim.Right - Width;
Top = desktopDim.Bottom - Height;
}
Creating the shape
I build the circle as a bunch of circle pieces that I generate from code behind:
private Path CreateCirclePart()
{
var circle = new CombinedGeometry
{
GeometryCombineMode = GeometryCombineMode.Exclude,
Geometry1 = new EllipseGeometry { Center = _center, RadiusX = _r2, RadiusY = _r2 },
Geometry2 = new EllipseGeometry { Center = _center, RadiusX = _r1, RadiusY = _r1 }
};
var sideLength = _r2 / Math.Cos((Math.PI/180) * (ItemAngle / 2.0));
var x = _center.X - Math.Abs(sideLength * Math.Cos(ItemAngle * Math.PI / 180));
var y = _center.Y - Math.Abs(sideLength * Math.Sin(ItemAngle * Math.PI / 180));
var triangle = new PathGeometry(
new PathFigureCollection(new List<PathFigure>{
new PathFigure(
_center,
new List<PathSegment>
{
new LineSegment(new Point(_center.X - Math.Abs(sideLength),_center.Y), true),
new LineSegment(new Point(x,y), true)
},
true)
}));
var path = new Path
{
Fill = new SolidColorBrush(Colors.Cyan),
Stroke = new SolidColorBrush(Colors.Black),
StrokeThickness = 1,
RenderTransformOrigin = new Point(1, 1),
RenderTransform = new RotateTransform(0),
Data = new CombinedGeometry
{
GeometryCombineMode = GeometryCombineMode.Intersect,
Geometry1 = circle,
Geometry2 = triangle
}
};
return path;
}
First step is to build two concentric circles and to combine them in a CombinedGeometry with CombineMode set to exclude. Then I create a triangle just tall enough to contain the section of the ring that I want, and I keep the intersection of these shapes.
Seeing it with the second CombineMode set to xor may clarify:
Building the circle
The code above uses some instance fields that make it generic: you can change the number of pieces in the circle or their radius; it will always fill the corner.
I then populate a list with the required number of shape, and add them to the grid:
private const double MenuWidth = 80;
private const int ItemCount = 6;
private const double AnimationDelayInSeconds = 0.3;
private readonly Point _center;
private readonly double _r1, _r2;
private const double ItemSpacingAngle = 2;
private const double ItemAngle = (90.0 - (ItemCount - 1) * ItemSpacingAngle) / ItemCount;
private readonly List<Path> _parts = new List<Path>();
private bool _isOpen;
public MainWindow()
{
InitializeComponent();
// window in the lower right desktop corner
var desktopDim = SystemParameters.WorkArea;
Left = desktopDim.Right - Width;
Top = desktopDim.Bottom - Height;
_center = new Point(Width, Height);
_r2 = Width;
_r1 = _r2 - MenuWidth;
Loaded += (s, e) => CreateMenu();
}
private void CreateMenu()
{
for (var i = 0; i < ItemCount; ++i)
{
var part = CreateCirclePart();
_parts.Add(part);
Container.Children.Add(part);
}
}
ItemSpacingAngle define the blank between two consecutive pieces.
Animating the circle
The final step is to unfold the circle. Using a rotateAnimation over the path rendertransform make it easy.
Remember this part of the CreateCirclePart function:
RenderTransformOrigin = new Point(1, 1),
RenderTransform = new RotateTransform(0),
The RenderTransform tells that the animation we want to perform is a rotation, and RenderTransformOrigin set the rotation origin to the lower right corner of the shape (unit is percent).
We can now animate it on click event:
private void WindowClicked(object sender, MouseButtonEventArgs e)
{
for (var i = 0; i < ItemCount; ++i)
{
if (!_isOpen)
UnfoldPart(_parts[i], i);
else
FoldPart(_parts[i], i);
}
_isOpen = !_isOpen;
}
private void UnfoldPart(Path part, int pos)
{
var newAngle = pos * (ItemAngle + ItemSpacingAngle);
var rotateAnimation = new DoubleAnimation(newAngle, TimeSpan.FromSeconds(AnimationDelayInSeconds));
var tranform = (RotateTransform)part.RenderTransform;
tranform.BeginAnimation(RotateTransform.AngleProperty, rotateAnimation);
}
private void FoldPart(Path part, int pos)
{
var rotateAnimation = new DoubleAnimation(0, TimeSpan.FromSeconds(AnimationDelayInSeconds));
var tranform = (RotateTransform)part.RenderTransform;
tranform.BeginAnimation(RotateTransform.AngleProperty, rotateAnimation);
}
Not actually answering this, but I liked your question enough that I wanted to get a minimal proof of concept together for fun and I really enjoyed doing it so i thought I'd share my xaml with you:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing" x:Class="WpfApplication1.Window2"
Title="Window2" Height="150" Width="150" Topmost="True" MouseLeftButtonDown="Window2_OnMouseLeftButtonDown"
AllowsTransparency="True"
OpacityMask="White"
WindowStyle="None"
Background="Transparent" >
<Grid>
<ed:Arc ArcThickness="40"
ArcThicknessUnit="Pixel" EndAngle="0" Fill="Blue" HorizontalAlignment="Left"
Height="232" Margin="33,34,-115,-116" Stretch="None"
StartAngle="270" VerticalAlignment="Top" Width="232" RenderTransformOrigin="0.421,0.471"/>
<Button HorizontalAlignment="Left" VerticalAlignment="Top" Width="41" Margin="51.515,71.385,0,0" Click="Button_Click" RenderTransformOrigin="0.5,0.5">
<Button.Template>
<ControlTemplate>
<Path Data="M50.466307,88.795148 L61.75233,73.463763 89.647286,102.42368 81.981422,113.07109 z"
Fill="DarkBlue" HorizontalAlignment="Left" Height="39.606"
Stretch="Fill" VerticalAlignment="Top" Width="39.181"/>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
</Window>
And it looks like this:

Placing a Canvas within Canvas XAML

I want to add a number of canvas to another canvas but the following code doesn't seem to work, the application compiles but only a blank window is displayed. Ideally this would show the canvases in a diagonal line.
Here is my vb.net code:
For r As Integer = 1 To 10
X += 5
Y += 5
Dim c As Canvas = New Canvas()
Dim s As SolidColorBrush = New SolidColorBrush
s.Color = Color.FromRgb(255, 0, 0)
c.Background = s
c.Name = "cnv" + CStr(X)
c.Margin = New Thickness(X, Y, 0, 0)
cnvOverLay.Children.Add(c)
cnvOverLay.UpdateLayout()
Next
I have tried to add multiple buttons using dim b As Button = new Button() instead of creating a new canvas every time, that worked fine.
Am I missing something simple?
You cannot see the canvases be because the do not have a width and a height.

Can VBA Forms have a Flow Layout?

I'm guessing this is impossible, but here goes.
Java and more recent .Net updates are capable of a Flow Layout - where a layout manager re-arranges the form controls to fit in the available space.
I've only seen VBA & WinForms using hard-coded absolute positions.
Has anyone encountered a flow-layout manager in this context?
Access 2007 and later versions implement this functionality via anchoring: Make controls stretch, shrink, or move as you resize a form
If you want to do it in earlier versions you can roll your own using the On Resize event of the form.
I have a form which is laid out like this. All of my controls are sequentially named based on their vertical position: txt_R1, txt_R2, txt_R3 etc...
When the Form loads, it looks like this:
When I update the combo box, the code below executes:
Dim s_tier As String
Dim s_rate As String
Dim s_lbl_Rate As String
Dim s_lbl_Tier As String
Dim s_obj As String
Me.TXT_Min.Visible = True
Me.LBL_MIN.Visible = True
Me.TXT_Min.Value = 0
Me.TXT_Scale.Visible = True
Me.lbl_Scale.Visible = True
Me.TXT_Scale.Value = 0
Me.txt_MinMax.Visible = True
Me.lbl_MinMax.Visible = True
Me.txt_MinMax.Value = 0
s_tier = "TXT_T"
s_rate = "TXT_R"
s_lbl_Rate = "LBL_R"
s_lbl_Tier = "LBL_T"
For i = 1 To numActive
'Tier Text Box
s_obj = s_tier & i
Me(s_obj).Visible = True
Me(s_obj).Value = "NULL"
'Tier Label
s_obj = s_lbl_Tier & i
Me(s_obj).Visible = True
'Rate Text Box
s_obj = s_rate & i
Me(s_obj).Visible = True
Me(s_obj).Value = "NULL"
'Rate Label
s_obj = s_lbl_Rate & i
Me(s_obj).Visible = True
Next i
'set last tier to infinite, since last tier typically goes on forever
s_obj = s_tier & numActive
Me(s_obj).Value = ChrW(&H221E)
Me(s_obj).FontSize = 16
'Make Test button visible and move to appropriate place
s_obj = s_lbl_Tier & (numActive + 1)
Me.Btn_Test.Top = Me(s_obj).Top
Me.Btn_Test.Left = Me(s_obj).Left
Me.Btn_Test.Visible = True
s_obj = s_tier & (numActive + 1)
'Make Test button visible and move to appropriate place
Me.btn_SQL.Top = Me(s_obj).Top
Me.btn_SQL.Left = Me(s_obj).Left
Me.btn_SQL.Visible = True
Me.Refresh
The refreshed form now looks like this if "1" is selected in the combo box:
... Or if "2" is selected in the combo box:
... Or if "3" is selected in the combo box:
The key to my method is to use the sequential naming convention as a way to exploit the
for i = 1 to numactive
piece of code. Once the loop ends, all of the static controls are visible. I can add 1 the numactive variable to determine where the first invisible control is, and anchor my 'floating' controls to that position.
This method can be tweaked to actually place any control into any position using offsets instead of the position of other controls. Let your imagination run wild!
WinForms of course has the FlowLayoutPanel and TableLayoutPanel..
There's an example of AutoLayout for Winforms on MSDN.

TabControl - Scrolling between tabs

I'm trying to implement in WPF tab that behaves like the one in IE9.
When you open in the last many tabs, they are getting smaller and also to buttons are showen in the left and in the right, for scrolling between the tabs.
Any help would be very appritiated.
create two main tab (main tabs are these two tab in answer) like this
<TabItem Header="«" Name="LeftTab"/>
<TabItem Header="»" Name="RightTab"/>
set the visible of them to hiden. now add all tabs you want(with c# code or xaml) but dont forget set tag for all tab you add like below
<TabItem Header="new" Name="tiNew" Tag="1"/>
<TabItem Header="edit" Name="tiEdit" Tag="2"/>
...
now when tabs count go more than normal and you cant show all in 1 page Do Under :
1.change visible of two main tab..
bool is_Left_Right_tabVisible = false;
if (tabControl1.Items.Count > 8)
{
LeftTab.Visibility = System.Windows.Visibility.Visible;
RightTab.Visibility = System.Windows.Visibility.Visible;
is_Left_Right_tabVisible = true;
}
else
{
LeftTab.Visibility = System.Windows.Visibility.Hidden;
RightTab.Visibility = System.Windows.Visibility.Hidden;
is_Left_Right_tabVisible = false;
}
2.hidden all extra tab and only show some of them (example : show two main tab And show tab with tag 1-8)
3.if user click on main tabs (left or right tab) hidden one tab and visible another tab (example: you have lefttab-1-2-3-4-righttab when user click on right hidden NO 1 and vsible No 5 And focus on No 5)
private void RightTab_MouseUp(object sender, MouseButtonEventArgs e)
{
if (is_Left_Right_tabVisible)
{
TabItem ti = sender as TabItem;
if (ti.Name == "RightTab")
{
//find right tab must set to visible
int Showtabindex = 0;
var t1 = tabControl1.Items.OfType<TabItem>().Where(x => x.Visibility == System.Windows.Visibility.Hidden);
foreach (var item in t)
{
if (((int)item.Tag) > Showtabindex)
Showtabindex = (int)item.Tag;
}
//find left tab must go invisible
int Hiddentabindex = Showtabindex;
var t2 = tabControl1.Items.OfType<TabItem>().Where(x => x.Visibility == System.Windows.Visibility.Visible);
foreach (var item in t2)
{
if (((int)item.Tag) < Hiddentabindex)
Hiddentabindex = (int)item.Tag;
}
(tabControl1.Items[Hiddentabindex] as TabItem).Visibility = System.Windows.Visibility.Hidden;
(tabControl1.Items[Showtabindex] as TabItem).Visibility = System.Windows.Visibility.Visible;
//you can create drag and drop for tabs then user can change tab TAG
}
else if (ti.Name == "LeftTab")
{
//.....
}
}
}
i know it was abit hard but when i create a good user control i feel good .
but dont forget in this usercontrol we use tabcontrol we can create a custom tab control from first and dont use this tabcontrol.
you also can create animation for tabs when those change opacity and move animation would be good check this post

Resources