As my first WPF project, I am attempting to build an application to play a card game similar to Magic the Gathering. It is not clear to me how to lay out the main play area. You can see some examples that are similar to what I am attempting by looking at example 1 or example 2. The chat/info areas on the right would be separate user controls.
The cards must maintain their aspect ratios, and each play area would start with 10 columns and two rows of cards. As more cards are played, the number of columns and/or rows may change. Each player area may have a different number of columns and/or rows. Cards may overlap, and may be placed sideways (tapped). Cards in all areas should be the same size (although they may be cropped in some areas). Cards do not need to lie exactly on the grid (they do not necessarily snap-to-grid).
When the user hovers the mouse over a card, it should expand to a significantly larger size using an animation. A card in one player area may overflow into the other player's area when expanded (but only as long as the mouse hovers).
Given these requirements, I am tempted to use one large user control derived from Canvas with image objects for each card (along with other shapes to delineate the areas). This implies that I will be doing a lot of work during the OnRenderSizeChanged event to position the child items within the canvas (manual layout).
Using a grid does not seem feasible to me, due to the free-form placement and overlap.
Decomposing the play area into smaller user controls would leverage the WPF layout capabilities, but it seems like decomposition would prevent the cards from expanding into adjacent user controls during the mouse-over, so that doesn't seem feasible either.
Is there a better alternative to one large canvas-based control? It seems wrong to be doing manual layout in WPF, but I cannot see an alternative.
This sounds like a great scenario for Composite Application ala Prism. It provides solid framework for implementing regions, modules, sending message between modules etc... From looking at your screen captures, developing a shell with different regions and dropping modules into them would probably greatly benefit your layout. As for the cards themselves, perhaps they could be modules as well?
Check out:
http://msdn.microsoft.com/en-us/library/ff649780.aspx
Particualy good examples come with the download package including a stock market like application and event aggregator example.
You said:
Decomposing the play area into smaller user controls would leverage the WPF layout capabilities, but it seems like decomposition would prevent the cards from expanding into adjacent user controls during the mouse-over, so that doesn't seem feasible either.
But this is not correct. Decomposition is absolutely the right approach to take, and this would not prevent the cards from expanding into adjacent user controls. The reason being that you can use a RenderTransform rather than a LayoutTransform. See this example, by Charles Petzold, or this article, to visualize the difference. Because a RenderTransform is applied after the layout has already occurred, your cards would be able to expand outside their bounds.
Given that decomposition is the right approach, I would arrange your various card collections into a Grid, with each collection being an ItemsControl. The ItemsControl should bind its ItemsSource property to some collection, and then you can provide a custom ItemTemplate that would display the image and any other information. I would be hesitant to use a Canvas, as this would restrict you to hard-coding the positions for the cards (which is a very WinForms-like solution for a problem that can be far more elegantly solved). Take advantage of WPF's fantastic layout engine and use nested grids and items controls to create a dynamic layout. This will ensure that your game board looks good at any resolution and when stretched to various sizes.
I recommend you take a look at this guys project . In java I know but if I was to go the route of building a card game. That would be what I would go off of.
A lot of canvases inside of a grid could help you here, the canvas will allow the content to render outside of its bounds, as long as you turn ClipToBounds to false, and you will be given much more control over exact placement of the cards than with other schemes. You will also get the powerful functionality of a grid control, allowing you to add and remove columns and rows as needed (though you will also have to dynamically add and remove canvasses, though this isn't too difficult.
If you're worried about the contents of your "Card" moving around when the box is rescaled, surround it in a viewbox. It will manage all your scaling for you, and ensures your card uses as much real estate as it can get. Alternatively you could use a RenderTransform, but a lot of these might slow your program down (Experts: does the viewbox operate using RenderTransforms? If so this point is moot)
To ensure the cards maintain their aspect ratios make sure each Image's Stretch attribute is set to "Uniform", making them all keep the same size could be done by designating a master card, and binding heights and widths of all subsequent cards to this original card, though that is a little messy and doesn't allow the cards to expand. Another solution is to set a single size for each card manually, animating this when you want to expand or shrink.
Related
I'm trying to build a timeline-like control for a project, but I have limited experience with WPF, and don't really know where to start. The requirements are fairly simple: I have an ObservableCollection of objects that have a timestamp property, and I need to be able to select one or more of them and drag them back and forth on a "timeline". All of the objects will be rendered the same size since there's no concept of a start/end time. Here is a mockup of what I'm trying to build:
I've spent hours searching for examples or tutorials, but when I search for "timeline" controls most of the results address a completely different problem:
Rather than going with the classic override of the Thumb control, I threw together a quick framework based off your mockup:
ZIP: http://www.mediafire.com/file/fidg8ea88ofoki4/TimelineFramework.zip
VirusTotal: https://www.virustotal.com/en/url/7579b365749d07eb743643ab118de71c7dd09cb03df7a8b28fbf3cec816ff4cc/analysis/1484802709/ and https://www.virustotal.com/en/file/4899aa96234e1e69c4e935f7d692e46789d8b4b7a5afd4c354937ed921986b20/analysis/1484802463/
It's pretty basic in terms of WPF as it's mostly C# with little XAML, so you can probably figure it out real fast and then be on your way to adapting it for your specific needs.
In the demo app, it looks like this:
The blue bands are draggable, with the thick center line representing their true placement and the faded side blue making for a bigger grip to click on. Hovering over a band shows its placement in the Tooltip. Of course, you can restyle and adjust all the visuals to your needs.
In my graphic calculator, I am using canvas as a plane on which graphs of functions are rendered. I have noticed that whenever I input complex functions (I use bezier curves for that, so the more complex the function -> the more points I need to render for the graph to be smooth-looking) it gets quite laggy and overally doesn't perform well.
Which of these solutions are the least computationally costly / thus are the best approach?
1. (My current solution) Using huge Canvas inside a ScrollViewer that limits the view area
Cons I have found:
The whole canvas is rendered, even the non-visible part
Starts to lag when there is more than 50K elements on the canvas
2. Using just Canvas that is not so big, and management of panning / zooming through TransformMatrix
Cons I think there might be (solution not tried):
Won't it be even more laggy when it will have to redraw and recalculate everything dynammically?
3. Some other solutions?
Any help will be greatly appreciated.
If you can avoid it, you really don't want to be using discrete visuals to represent things like charts/graphs; they are very heavy, and are constantly participating in input handling and layout. I would recommend using WPF's drawing/geometry APIs directly. I would suggest implementing a custom control which performs its own rendering (see OnRender). I would also suggest implementing IScrollInfo so you can manage your own scrolling: you will always know the viewport size and position, which gives you the option of invalidating your geometry when scrolling, and then rebuilding only the parts of the graph that are actually in view. That should reduce the overhead significantly.
What are the principles of supporting different display size/modes/orientations in Metro/Winstore app using XAML/C# ? Are there guidelines?
At the moment I want to be able to display a list view with 2 tiles in portrait mode and 5 tiles in landscape. I want these 2/5 tiles to fill the screen width automatically on the mode change.
Shall I just bind witdth of the tile template to a property and calculate it manually or is there more elegant tools in the .NET 4.5 ?
The most straightforward solution would be to use a BasicPage template that uses a LayoutAwarePage base class and provides a visual state for each ApplicationViewState (FullScreenLandscape, Filled, Snapped, FullScreenPortrait). Then define two designs and use visual states to switch between the designs. You could handle Window.Current.SizeChanged events to update the dimensions to make the tiles be exactly the portion of screen size, but that would be counterproductive and might not actually be the best design since users might not immediately see that the content is scrollable and you would also need to resize fonts, images, etc. to fit the new size. You could put these in a Viewbox control too if you really want to map your content dimensions to screen size.
I am new to C# and WPF and I need to create a diagramming control similar to MS Visio but without direct user interaction. I have tree-like hierarchical data whose nodes can be of the same type. Quite like graphs whose vertices themselves contain graphs (i.e. vertices are subgraphs). I cannot use the Graph# library for several reasons.
The main requirements for my (customized) control are:
free moveable/draggable items (which represent hierarchical data)
items should have a box layout
items can be connected by arrows
Unfortunately, I don't know how to start. I tried several approaches like nesting ListBoxes but each approach had disadvantages. What do you think about nesting TreeViews and templating them? I need something like a Canvas container to freely position my items.
Do you have any suggestions? Thank you very much in advance.
If you need free movable/draggable items you probably need a degree of flexibility that built-in controls don't really provide. You're better off constructing your own controls, perhaps deriving from existing controls that provide close-enough functionality.
So for starters you'd have a control for a box item and a control for an arrow. The controls need to be movable and draggable inside a container, so you'll also need a container, probably derived from Canvas.
What I'd really recommend is to have a look at Model-View-ViewModel techniques; they can be daunting for a beginner but the benefits are immense. In this case, you'd have a collection of objects that represent your structure; all the objects will have, for starters, X and Y properties that define their coordinates. The objects are represented on the page by the previously mentioned controls, with bindings from their relevant properties to the properties of the objects. The objects are the ViewModel, and the controls represent the View.
Then, when you move the items with the mouse (the code for that is pretty easy), the properties of both the controls and the objects are automatically updated. More properties for the objects can include size, labels, and a collection of snap points that represent where arrows can connect to the object.
Arrows can be represented with the same concepts, except that instead of explicit X and Y coordinates they would have associated objects and snap points; then their coordinates would be automatically calculated based on the positions of the snap points.
Based on these structures, you can do actions exclusively from the ViewModel, like adding new items automatically connected to their parents, and have the view update based on that.
This is quite a broad topic so I really should stop now; I don't even what articles to recommend to get you started. Probably anything by Josh Smith on the topic of MVVM :P
I've searched around for an alternative way of drawing selection indicators for visual objects (like selected edges, lines etc.) without the use of ControlPaint.DrawReversibleFrame and related XOR methods. The reasons are unwanted XOR-ing "artifacts", reversibility not applying to bitmaps, no control of the actual visual look and slowness.
On the other hand I want to avoid having to repaint the whole scene (map actually) if a user decides he wants to deselect an object or two, because the repaint could be quite expensive.
So the only alternative I can see is implementing some basic drawing logic directly on a Bitmap, but with storing the previous contents of the pixels before they change. Then (in theory) I would be able to reapply old contents of, say, an selected edge rectangle if the user chooses to deselect that edge.
My question is whether you think this is a good idea or do you see some other alternatives to my problem (within the GDI+)?
Thanks in advance
If the selection indicator is just drawn on the top of the unselected object, you can use two bitmaps, draw all the unselected objects on the background one and the selection indicators on the other, and paint them both on screen.
Else, you can do the same, except that you render the selected objects instead of just indicators.
Only store the rectangles "of interest" in an off screen buffer. And repaint when the focus is lost. . . Or if you can redraw just the portion as it appears normally based on in memory data you should be fine. Otherwise it seems that you have the gist of it.