Difference between Canvas and Grid to Move, Resize, Rotate UIElements - c#

I want to develop a editor that can add dynamically Controls and after to move, resize or rotate to build a window with this UIElements.
My question is who is better for a Container of this UIElements, a Grid or a Canvas?
Canvas are working in absolute position, maybe have better precision for transforming. But is less responsive when I will display the App in different screen resolutions? I doesn't know very well about the pros/cons from Grid or Canvas.
I made a example with a Canvas and Grid to move a UIElement with this code:
private void ui_MouseMove(object sender, MouseEventArgs e)
{
if (m_IsPressed)
{
UIElement ui = (UIElement)sender;
TranslateTransform transform = new TranslateTransform();
transform.X = Mouse.GetPosition(MyGridOrCanvas).X;
transform.Y = Mouse.GetPosition(MyGridOrCanvas).Y;
ui.RenderTransform = transform;
}
}
But with the Canvas or Grid, when I click the UIElement and without moving, the UIElement always moved x,y from my cursor. Maybe isn't the best way to do this. If you have also tutorials about how to build this features will help me too. I'm new with this stuff.
Thank you very much and greetings!

I'll just provide a short answer for this question as it is likely to be closed by the community here for being too subjective. I can see one close vote already.
So, in my opinion, the Canvas is a much better control to use for this purpose. For one reason, it does not have the considerable layout requirements of the Grid and so it is more efficient. The other main reason is that using the Canvas.Top and Canvas.Left properties to move the items is perfect... to move items in other Panels, you often have to make do with setting the Margin property instead, which is far from ideal.
As for your items moving when being clicked on... that's just a bug in your code doing that, it's not the normal behaviour - a control won't move on its own unless we tell it to.

Related

Toolbar on right side of the screen in wpf

I am trying to make a WPF application in which there is a drag able toolbar on the screen through which user can select different type of tools and use it on canvas. Also can someone tell me how to make a transparent canvas. A good example would be from this picture in which there is drag able toolbar on right side of the picture. And the user can also work on any window he wants. I am new to WPF and I am trying to find a solution to my problem for quite a while now. Can someone guide me in the right direction...
Background DP default value is null. When a Background is set to null the displayed Color is White and mouse interactions don't work. You need to set Canvas's, ListBox's and ListBoxItem's Background to Transparent to see the Background of the Parent Control
<Canvas Background="Transparent"/>
Rather than a toolbar, think of that as a window.
I would take a look at avalondock.
A transparent canvas:
<Canvas Background="Transparent"
As an aside, this is a couple of steps on from wpf beginner level.
If you take a look at this:
https://imgur.com/4n7vH8k
The user is designing a game scenario. They drag units out the panel on the left ( it's a treeview ) onto the canvas on the right. Only this is not just a plain canvas, it's an itemscontrol with a canvas as the itemspresenter. That allows me to template out the units from a collection of unit view models. It's using the mvvm pattern.
If you've not come across this technique it's a bit strange. Here's a couple of samples to take a look at which templates out different viewmodels into different UI objects. https://1drv.ms/u/s!AmPvL3r385QhgooJ94uO6PopIDs4lQ
https://1drv.ms/u/s!AmPvL3r385QhgooLcGrZOSwFswa-Dg
The datatype is used to decide what you get in the view for what viewmodel.
You have a bit of a complication in that you decided you want a dockable panel usable in multiple windows. Maybe that's not a must have.
Drag drop in my app isn't actually drag drop and relies on an odd aspect of a canvas. They don't clip, so you can add something to a canvas but have it positioned off the canvas.
As you start dragging a unit, it's viewmodel is added to the collection bound to my units itemscontrol. That templates it into the canvas as a piece. I work out the location compared to the canvas, so it'll have a negative X aspect which I bind to Canvas.Left.
Each unit is inside a thumb. A thumb is the rectangle you drag up and down on or side to side on a slider. They are designed for dragging. This way dragging is smooth and I can easily have a unit under the cursor that's being dragged.

Windows store app, horizontal scrolling when too much text

I am making an app for the Windows store (xaml/c#), in this app i create a list of properties of a file. One properties is the file path, this is always too long. my solution would be to make this side scrolling when this textblock is selected.
the text would start to scroll when selected to make all the information readable. (ticker bar)
I can’t find a property to achieve this, and I find it difficult to make a custom function for this. Can you help me?
I'd reconsider the idea. I had the idea many times and it was always rejected by designers. I think animating text is likely to be more annoying than clipped text. A better way might be to either wrap it in place or if you are in a list with limited item height - only show the full text after it was tapped - either with some popup or in the details view of the tapped item.
Having said that - to animate it you'd put the TextBlock inside of a Canvas, set the Clip of the Canvas to a RectangleGeometry that defines your clipping region (and update it on size updates), then animate the Canvas.X property of the TextBlock. The problem with that is that Canvas.X is not an "independent" property and so you'd need to set DoubleAnimation.EnableDependentAnimation="true" on the animation and could still get a fairly choppy animation.
A better choice might seem to be to animate the RenderTransform of the TextBlock (e.g. set it to a TranslateTransform and target the X property of the transform in the animation), but last time I checked - this could animate the TextBlock in an already clipped form, so you still wouldn't see the part of it that doesn't fit on screen. You could try that though.
Putting the TextBlock in a ScrollViewer might work better, but it would suffer from similar problem as the Canvas solution since the ScrollViewer doesn't even have an animatable offset property. In Windows 8.1 you get built in animations when you call ScrollViewer.ChangeView(), but that would likely animate too quickly. It is possible with the help of a proxy dependency property or other per-frame dependent animation as in the ScrollToHorizontalOffsetWithAnimation() ScrollViewer extension method in WinRT XAML Toolkit.

Center and Stretch on a Standard WinForms Panel

So, doing what I'm attempting to do is trivial in WPF, but in WinForms it seems to be a bit problematic:
When using a TableLayoutPanel, you can simply set the Anchor properties to NONE to center the control within the cell of the TableLayoutPanel and then set Anchor.Right | Anchor.Left flags on the control to stretch it to the size of the cell. This behavior does not seem to work properly when using a standard WinForms Panel container. When setting the Anchor property on the child control (TextBox) within the Panel the control does not appear to stretch out, nor center itself within the container.
I've looked up some other answers regarding similar issues to this, but I feel like I'm missing something here. Most of them say just use the Anchor property, but that doesn't not appear to work. Does this need to be manually calculated on load (and each resize), or can the Anchor property actually assist me with this?
Keeping a Control centered works automatically only if you combine stretching it with Anchors.
If you want it centered without stretching it you'll have to do a little bit of math in the Resize event:
private void tableLayoutPanel1_Resize(object sender, EventArgs e)
{
yourControl.Left = (yourControl.Parent.ClientSize.Width - yourControl.Width) / 2;
}
For centering vertically the same rules apply.
With regard to the disappearing ErrorProvider: The ErrorProviders need a little space, on my machine 12 pixels will do. To provide that space for the rightmost cells in an TableLayoutPanel you can set its padding like this:
this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(0, 0, 12, 0);
Note how this nicely adds the padding between the Cellborders, if you have any, and the outside.
It seems that MSDN has a page dedicated to this already. (although this mentioned a button, the idea remains the same)

Translate/Scale Transform and window resizing

I'm making a little chess game in wpf, and I'm having trouble to find the right way I should move and display pieces on the chessboard...
To draw the chessboard I use a UniformGrid (8 * 8) which I fill on init in "code behind" with Rectangle shapes.
Then I want to add my pieces on this grid, which are png images in a Image control I also create in "code behind".
I thought about putting these images in the same cell of the grid as my Rectangle controls, but I see the issue that I wouldn't be able to animate the move of a piece that way, since it will go from one location to another directly.
So I thought about adding the pieces to the parent control, and then use the RenderTransform property to set their positions.
The thing is, I can't figure out what I have to do so that if the parent control is resized the pieces stay at the right position.
Is there a way to set the translation once and for all without having to redefine it at resize? I thought about assigning the position and size of the Rectangle elements on the pieces control, but this doesn't seem to be doable in wpf...
Am I just doing it all the wrong way and there is a better option to do this?
Thanks for your help, any suggestions are welcome.

Canvas Click events in Silverlight when not over a UIElement

I have a canvas object and I am sprinkling fantastic controls all over it. I'm using a ScaleTransform object to scale the canvas so I can zoom in/out.
I have wired up the controls so that I can drag them around, and the drag and drop works well by using MouseLeftButtonDown, MouseLeftButtonUp, and MouseMove. Now, I want to work on enabling an event when I click only on the Canvas. When I read the docs for the canvas object, I see that the MouseLeftButtonDown event only fires when it's over a UIElement.
Occurs when the left mouse button is
pressed (or when the tip of the stylus
touches the tablet PC) while the mouse
pointer is over a UIElement.
(Inherited from UIElement.)
Unfortunately, I want the opposite behavior. I want to know when the mouse is clicked on the Canvas while the mouse pounter isn't over any controls. Since I'm new to Silverlight, I could be doing this the wrong way. Is there something I have overlooked? Am I going about this the wrong way? I'm looking for a little help, and perhaps a lot of direction.
I'm no Silverlight guru, but could you add a transparent UIElement to the Canvas, below all other UIElements, and use it to determine if the user has clicked outside of any of the other drag/drop-able elements.
You want to know when a click happens on the Canvas and isn't over other controls?
The most natural thing is to capture the Canvas's MouseLeftButtonDown. Inside of that event, take a peak to see where the click happened. Then peak at the UIElements under the click. I recommend you keep everything in absolute coordinates to keep things straight. Something like:
void Page_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Point p = e.GetPosition(null);
var elements = VisualTreeHelper.FindElementsInHostCoordinates(p, App.Current.RootVisual);
foreach (var element in elements)
{
//Figure out if you're over a particular UI element
}
}
I think you may be interpreting the documentation wrong. According to MSDN, Canvas itself is an implementation of a UIElement:
System.Windows.UIElement
System.Windows.FrameworkElement
System.Windows.Controls.Panel
System.Windows.Controls.Canvas
From my experience, and correct me if I'm wrong, MouseLeftButtonDown usually only fires for the top-most UIElement clicked. So if you implement MouseLeftButtonDown for your Canvas, it should only fire when the Canvas is clicked, and NOT when the buttons are clicked. I'd say try it out first.
In WPF, I think this would be easily solved by routed events. However, Silverlight didn't get this feature. You may want to check out VisualTreeHelper.FindElementsInHostCoordinates. This article covers it a little bit.
http://www.andybeaulieu.com/Default.aspx?tabid=67&EntryID=95

Categories

Resources