displaying a canvas at two positions simultaneously - c#

In C#, using WPF components, Is it possible to display a canvas (whose contents change at run time based on user input) at two positions on the screen? or in two windows? So basically, whatever happens in the canvas positioned at one place happens in the canvas positioned in the other place.

Do you need them both to be interactive?
If not, then you could use a VisualBrush to duplicate the Canvas to another location. The VisualBrush part won't be interactive, but it will mirror what happens on the other one.

So, there are 2 solutions :
create control containing your canvas & add them to required places and bind to your VM
use visualbrush as #Tim mentioned, example:
<Window x:Class="visualbrushmirroringstackoverflow.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">
<Window.Resources>
<VisualBrush x:Key="MirrorBrush"
Visual="{Binding ElementName=TargetCanvas}" TileMode="None"
Stretch="None" AutoLayoutContent="False"/>
</Window.Resources>
<StackPanel>
<Button Click="Button_Click" Content="Add Random Rects" Margin="5"/>
<Border BorderThickness="1" BorderBrush="Black" Margin="5">
<Canvas x:Name="TargetCanvas" Width="100" Height="100"
Background="White" />
</Border>
<Border BorderThickness="1" BorderBrush="Black" Margin="5">
<Rectangle Width="100" Height="100"
Fill="{StaticResource MirrorBrush}" />
</Border>
</StackPanel>
handler in code behind:
private void Button_Click(object sender, RoutedEventArgs e)
{
var rnd = new Random();
var element = new Rectangle { Fill = Brushes.Black, Width = 5, Height=5 };
Canvas.SetLeft(element, rnd.Next(100));
Canvas.SetTop(element, rnd.Next(100));
TargetCanvas.Children.Add(element);
}

If you're populating and updating the Canvas through databinding, you can create a usercontrol that defines the Canvas and all of it's styles, templates etc and bind each instance of that usercontrol to the same source object. Even in different windows, because they are updating from the same object in memory they should appear synchronised.

I had a same problem where i was asked to display a canvas in other window while retaining the original canvas.
What i did and you can do is this:
Since a single child cannot have multiple parents so you can make a copy of your original by serializing them using XamlReader.Save.
Put this canvas in a ViewBox (so that it stretches to its parent). Set contents of new window as this ViewBox.
Canvas copycanvas = XamlReader.Parse(XamlWriter.Save(OriginalCanvas)) as Canvas;
ViewBox vb = new ViewBox() { Stretch.Uniform, Child = copyCanvas };
Windows newwin = new Window() { Content = vb };
newwin.ShowDialog();

Related

How to open a new WPF user control in a WPF user control? [duplicate]

My goal is to attach a new image control while the application is running.
img = new System.Windows.Controls.Image();
img.Margin = new Thickness(200, 10, 0, 0);
img.Width = 32;
img.Height = 32;
img.Source = etc;
I've tried
this.AddChild(img);// says must be a single element
this.AddLogicalChild(img);// does nothing
this.AddVisualChild(img);// does nothing
It was never this difficult to add a element with forms.
How can I simply attach this new element to the main window (not another control) so that it will show up.
Solved it, I named the grid main, and from there I was able to access the children attribute and the add function
main.children.add(img);
<Window x:Class="Crysis_Menu.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" Loaded="Window_Loaded" AllowsTransparency="False" Background="White" Foreground="{x:Null}" WindowStyle="SingleBorderWindow">
<Grid Name="main">
<Button Content="Run" Height="23" HorizontalAlignment="Left" Margin="12,12,0,0" Name="btnRun" VerticalAlignment="Top" Width="151" Click="btnRun_Click" />
<TextBox Height="259" HorizontalAlignment="Left" Margin="12,40,0,0" Name="tbStatus" VerticalAlignment="Top" Width="151" />
</Grid>
</Window>
You should have only one root element under window. Adding the image using this.AddChilda adds the image as child of window, but you probably have some other child defined(Grid for example). Give a name to this child (Grid in the example) and then in the code behind add the image to the Grid
Example :
<Window>
<Grid x:Name="RootGrid">
</Grid>
</Window>
Then in the code behind use
RootGrid.Children.Add(img);
What is this in your case? You can try this.Content = image; or this.Children.Add(image);
If your this is indeed a Window, you should know that Window can have only a single child, which you put into Content. If you want several items in Window, usually you put some appropriate container (for example, Grid or StackPanel) as Window's content, and add children to it.
Vlad got the solution. I used it :
var grid = this.Content as Grid;
// or any controls
Label lblMessage = new Label
{
Content = "I am a label",
Margin = new Thickness(86, 269, 0, 0)
};
grid.Children.Add(lblMessage);

How to create an automatic animated carousel cyling images using C# or XAML?

I have done carousels in web development, but animating them in WPF through XAML or C# is new to me. There are examples on the web, but they either are outdated or not what I am looking for. Even when I play around with source code of other projects, it's not what I hope for.
I want to have images sliding left-to-right (horizontally) automatically. The user cannot interact with the images to stop the sliding. While I can do this manually in a ScrollViewer, the process is manual...
ScrollViewer doesn't have any dependencies for animation. I tried using this to see if it is possible, but the application would always crash. Example I used..
Another attempt I've tried is storing images in a StackPanel, making sure the StackPanel is the width of one of my images, then having DispatcherTimer set to animate the TranslateTransform's X property. But...that didn't go anywhere.
Using a ScrollViewer or StackPanel is not important at all. I just want to have a carousel-like effect automatically transitioning through images. Sort of like THIS
I'm currently using Visual Studio 2012 and 2013, if it helps.
Is there a way to do this?
I' ve prepared exemplary carousel in wpf. You might want to use the code in form of UserControl for instance. As you proposed I prepared carousel with use of StackPanel. Code of my form looks as follows:
<Window x:Class="WpfApplication2.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">
<Window.Resources>
<Storyboard x:Key="CarouselStoryboard">
<DoubleAnimation
Storyboard.TargetName="CarouselTransform"
Storyboard.TargetProperty="X"/>
</Storyboard>
</Window.Resources>
<Canvas>
<StackPanel Name="Carousel" Orientation="Horizontal">
<StackPanel.RenderTransform>
<TranslateTransform x:Name="CarouselTransform" />
</StackPanel.RenderTransform>
<Button Height="350" Width="525" Content="Page1"/>
<Button Height="350" Width="525" Content="Page2"/>
<Button Height="350" Width="525" Content="Page3"/>
</StackPanel>
<Button Click="Left_Click" Content="Left" HorizontalAlignment="Left" Margin="10,164,0,0" VerticalAlignment="Top" Width="45">
</Button>
<Button Click="Right_Click" Content="Right" HorizontalAlignment="Left" Margin="448,170,0,0" VerticalAlignment="Top" Width="45"/>
</Canvas>
</Window>
The Storyboard element within WindowResources defines animation to be performed. It will change X property of TranslationTransform applied to StackPanel "Carousel" - this will result in animated movement of that panel. 3 buttons within the panel simulates 3 panels of the carousel. At the bottom there are 2 buttons - one for moving left and second for moving right. There are callback methods bounded to them. Code behind of the form looks like that:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private int currentElement = 0;
private void Left_Click(object sender, RoutedEventArgs e)
{
if(currentElement < 2)
{
currentElement++;
AnimateCarousel();
}
}
private void Right_Click(object sender, RoutedEventArgs e)
{
if (currentElement > 0)
{
currentElement--;
AnimateCarousel();
}
}
private void AnimateCarousel()
{
Storyboard storyboard = (this.Resources["CarouselStoryboard"] as Storyboard);
DoubleAnimation animation = storyboard.Children.First() as DoubleAnimation;
animation.To = -this.Width * currentElement;
storyboard.Begin();
}
}
currentElement field holds information which panel is currently being displayed to the user. Method AnimateCarousel actualy starts the animation. It refers to Storyboard defined in Resources and sets its DoubleAnimation To property to the value to which Carousel panel should be moved. Then by calling Begin method on storyboard it performs animation.

How to Set listbox location in WPF [duplicate]

This question already has answers here:
C# WPF how to set location,width and height of the controls programmatically?
(6 answers)
Closed 8 years ago.
i want to set listbox location. In Winform i did this by using this code listbox.Location but in WPF there is no listbox.Location property.
Edit 1:
var rect = txtBox.GetRectFromCharacterIndex(txtBox.CaretIndex);
var point = rect.BottomRight;
lstBox1.Visibility = Visibility.Visible;
//Want to achieved this
//TextBox.Location = point;
I am creating something like Intellisense with listbox
You should probably read up on WPF layouts, however to you can use the ListBox.Margin to position the ListBox in a hardcoded location.
listbox.Margin = new Thickness( 25, 200, 0, 0 );
or in XAML
<ListBox Margin="25,200,0,0"/>
A ListBox's location is determined relative to the control it is contained in. To set a location within it's parent control you can use the HorizontalAlignment, VerticalAlignment and Margin Properties.
Here is an example:
<Window x:Class="WpfApplication14.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>
<ListBox HorizontalAlignment="Left" Height="100" Margin="197,105,0,0" VerticalAlignment="Top" Width="100"/>
</Grid>
</Window>
Note - all these properties are available programmatically as well.
Thanks,
Eric
It all depends on what the parent panel is to determine how to set the position of your listbox. You'll need to read more about Layouts in WPF. Let's look at 2 panels to get you started, Grid and Canvas.
<Grid>
<ListBox x:Name="lb" HorizontalAlignment="Left" VerticalAlignment="Top"/>
</Grid>
lb.Margin = new Thickness(10,10,0,0);
The example above sets the ListBox lb in the Grid at position (10,10).
<Canvas>
<ListBox x:Name="lb"/>
</Canvas>
Canvas.SetTop(lb, 10);
Canvas.SetLeft(lb, 10);
The example above does the same for lb in a Canvas.
As you can see, it depends on what type of panel that you put your listbox into to be able to set the position correctly.

Message box with Image in WP7

Hi at present I am using a grid with Image and two Buttons for showing a custom message box in my WP7 application whose visibility is collapsed at first. All is working fine but I have to disable all the controls behind on the page when its visibility is visible. So its quite a overhead to enable/disable lots of control behind.
Is there a better solution for my requirement which are :(1) To show a message box having image and two button or textbox and (2) It should appear in the middle of page.
Thanks in advance!!
You can use built in Popup control with an attached behaviour written by Kent Boogaart, so it would behave like WPF Popup control with PlacementTarget and Placement:
<Popup b:PopupPlacement.PlacementTarget="{Binding ElementName=someElement}">
<b:Popup.PreferredOrientations>
<b:PopupOrientationCollection>
<b:PopupOrientation Placement="Top" HorizontalAlignment="Center"/>
<b:PopupOrientation Placement="Bottom" HorizontalAlignment="Center"/>
<b:PopupOrientation Placement="Right" VerticalAlignment="Center"/>
<b:PopupOrientation Placement="Right" VerticalAlignment="TopCenter"/>
</b:PopupOrientationCollection>
</b:Popup.PreferredOrientations>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0">My popup's contents</TextBlock>
<Image Grid.Row="1" .... />
</Grid>
</Popup>
See the article Silverlight Popup with Target Placement
Download a project
What I do in this situation is to add a Grid or Border to the page that has a transparent background and IsHitTestVisible = True. You can then add your image etc to the parent control (Grid/Border).
You need to make sure the parent control covers the whole page and then just center the dialog inside this control. When you toggle the visibility of the parent control then the transparent background will overlay the other controls on the page, effectively disabling them.
Here is an example. The uxMessageGrid is the parent control and the Border is the actual dialog. You then just need to make sure this is the last control added to the root element and toggle uxMessageGrid.Visibility in your code.
<Grid x:Name="uxLayoutRoot">
<Other Controls />
<Grid x:Name="uxMessageGrid"
Visibility="Collapsed"
Background="Transparent"
IsHitTestVisible="True">
<Border CornerRadius="0"
BorderThickness="1"
VerticalAlignment="Center"
HorizontalAlignment="Center"
BorderBrush="{StaticResource PhoneForegroundBrush}"
Background="{StaticResource PhoneBackgroundBrush}">
<TextBlock Margin="15"
Text="Message..."
TextWrapping="Wrap"/>
</Border>
</Grid>
</Grid>
Use the Custom Dialog box features of the Coding4Fun toolkit
http://coding4fun.codeplex.com/
The toolkit has many controls available beyond the standard Silverlight Toolkit and should more than meet your needs.
Try this one, may be it helps to you
StackPanel st = new StackPanel();
StackPanel st1 = new StackPanel();
Image image = new Image();
image.Height = 300;
image.Width = 300;
image.Source = new BitmapImage(new Uri("/PhoneApp1;component/Koala.jpg", UriKind.Relative));//Build Action=Resource
Button btnok = new Button();
btnok.Content = "Ok";
btnok.Click += new RoutedEventHandler(btnok_Click);
Button btncancel = new Button();
btncancel.Content = "Cancel";
btncancel.Click += new RoutedEventHandler(btncancel_Click);
st1.Orientation = System.Windows.Controls.Orientation.Horizontal;
st1.Children.Add(btnok);
st1.Children.Add(btncancel);
st.Children.Add(image);
st.Children.Add(st1);
ContentPanel.Children.Add(st);

Separating and recovering elements from TransformGroup in Silverlight

On my MainPage.xaml I have some custom UserControls which I want to be able to move all over the Grid surface. That is the reason why I am adding them all to TransformGroup:
this.transformGroup = new TransformGroup();
this.translation = new TranslateTransform();
this.scale = new ScaleTransform();
this.transformGroup.Children.Add(this.scale);
this.transformGroup.Children.Add(this.translation);
myCustomControl1.RenderTransform = this.transformGroup;
myCustomControl2.RenderTransform = this.transformGroup;
Now I can move all my custom controls what gives me "scrolling effect" on the Grid (something like scrolling the Bing Maps effect).
My problem is:
I want to be able to seperate my Custom control from the TransformGroup and move it independent from the rest. In myCustomControl.xaml.cs I have:
private void separateControlFromTransformGroup()
{
Grid parentGrid = (Grid)Parent;
this.transformGroup = (TransformGroup)this.RenderTransform;//backup copy of old transform group
newTransformGroup1 = new TransformGroup(); //new temporary transform group
TranslateTransform translation1 = new TranslateTransform();
CopyTranslateTransform((TranslateTransform)transformGroup.Children[1], translation1);//copy the values of transformGroup from the MainPage.xaml to temporary one (not reference)
ScaleTransform scale1 = new ScaleTransform();
CopyScale((ScaleTransform)transformGroup.Children[0], scale1);
newTransformGroup1.Children.Add(scale1);
newTransformGroup1.Children.Add(translation1);
foreach (myCustomControl brother in parentGrid.Children)
{
if (brother == this)
{
continue; (separate this control from the TransformGroup)
}
else
{
brother.RenderTransform = newTransformGroup1; //the rest of myCustromControls on the Grid in MainPage.xaml now have diffrent transform group. Now I can move selected control independent from the rest
}
}
}
After moving the separate myCustomControl (with new values) I can't connect it with the rest in a transformGroup and be able to move the all together againg. What should I Do? Is there any other way to make controls 'moveAble' on the Grid if none selected, or select just one if any selected?
Please help.
You should be creating a separate TransformGroupd for each user control. You might consider having a container control that you add all the user controls with it's own TransformGroup, this transform group will affect all the controls while the individual per control transform group is used to affect the individual controls.
You might also consider wiring this all together directly in XAML.
So the MainPage might have the layout Grid with a child Grid which acts as the container for all the Controls, this is what will be translated and scaled to affect all the child controls.
<UserControl x:Class="SilverlightApplication1.MainPage"
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"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<Grid x:Name="Container">
<Grid.RenderTransform>
<TransformGroup>
<TranslateTransform x:Name="ContainerTranslation" />
<ScaleTransform x:Name="ContainerScale" />
</TransformGroup>
</Grid.RenderTransform>
</Grid>
</Grid>
</UserControl>
Then the child controls can be added to the Constainer, each with their own Translation and Scale transform. The child control might be something like this.
<UserControl x:Class="SilverlightApplication1.EntityControl"
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"
d:DesignHeight="50" d:DesignWidth="50"
Width="50" Height="50">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RenderTransform>
<TransformGroup>
<TranslateTransform x:Name="Translation" />
<ScaleTransform x:Name="Scale" />
</TransformGroup>
</Grid.RenderTransform>
<Ellipse Stroke="Black" StrokeThickness="2" />
</Grid>
</UserControl>
The code behind can expose some properties that you can access to affect the Translation and Scaling of the Entity controls.

Categories