I don't know if this is the best way, but what I am trying to do is to create a collection of Shape objects and then bind it to a Canvas, then whenever I update these Shapes, or add new Shapes (rare), the Shape objects on the Canvas will update as well.
Btw the Shape objects are not all the same, some Lines, Rectangles, etc. Not sure if that matters.
What's the best way to do this?
If you look at the question Is it possible to bind a Canvas's Children property in XAML? and further down there is an answer from Ivan which uses an attached property you can bind to and it automatically updates the canvas children. I haven't tried it but looks like it should work. Seems the best solution to me. The other option is to use the ItemsControl with a DataTemplate for each type you want to show - however that seems a bit fiddly.
Related
I am just beginning to learn WPF with the MVVM Pattern.
At the moment I'm stuck on a problem where I want to graphically visualize my current Model object by drawing a shape with dimensions databound to the VM's current instance of my Model. (It should redraw itself when a property changes etc)
This is what I've achieved (almost how I want it to look..):
My current approach is to derive a class from the Shape class with some dependencyproperties databound to the Models properties. This worked just fine until I wanted to have different strokethicknesses etc for different parts of the shape.
What I've tried is separating the drawing into two custom shape objects (that will be enough for my flexibility demands at the moment), but the problem right now is that they will not align correctly and scale differently.
This is how it scales/aligns with two different custom shape objects:
I'm thinking that there is probably way more efficient and flexible ways to tackle this. Do you guys have any ideas?
Thanks
A few years ago I wrote a graphing application in Java. It stored edges and vertices in a QuadTree which I would loop through whenever I had to draw them.
Today I need to do something similar in WPF, however, I noticed that I have to add elements to a Children list inside a panel in order for it to draw. This is inefficient since now I am effectively storing two versions of the data. Removing elements is also costly compared to using quadtrees.
Are there any better ways of implementing this without having to use the Children List?
In WPF you usually do not use panels directly if you have a data source, instead you use some ItemsControl, bind its ItemsSource, set up the ItemsPanel to whatever panel you want to use, and create an ItemTemplate which defines how the items are to be displayed. (Canvas binding example)
This way of working with panels means you do not have manually take care of the Children collection, if your ItemsSource implements INCC it will stay in synch. I realize that this might be a bit difficult with your trees but maybe you can figure something out.
I have a tree- or menu-like data structure which I want to display in a Panel (specifically a self-made PolarPanel), but all items must be VisualChildren of the same panel.
If I define a HierarchicalDataTemplate, I need to create an ItemsControls and specify it as IsItemsHost, or am I mistaken here? Can I somehow reference the parent's ItemsHost?
<HierarchicalDataTemplate
DataType="{x:Type local:ItemsCollection}"
ItemsSource="{Binding Children}"
>
<!--/* "virtual" ItemsHost referencing the parent's ItemsHost? */-->
</HierarchicalDataTemplate>
(My first workaround was to have a GetAllTheChildren property in the root node which returns all children and all children of the SelectedChild, recursively. This doesn't easily work together with ObservableCollection, because changes have to bubble up to the root to refresh GetAllTheChildren again (which reloads more items than would be neccessary).)
I know I can do it in code-behind by creating and drawing the items' Views into the same parent, but I'm searching for a nice WPF, indirect, automagic way.
EDIT: I am now using an improved workaround, where all ItemControls / Panels are drawn on top of each other. This preserves the hierarchical aspect, which makes this a much better solution than the one mentioned above (with GetAllTheChildren). But it still doesn't answer my question...
This is what it looks like graphically:
Note how the hierarchical elements have to be arranged in the same space.
Is there a clean and simple solution to this?
I must admit that the graphic result is very attractive, even I wouldn't know how to use that kind of control!
To answer to your question, I never tried to share the same panel as host, but I don't think would be possible. That would break the visual tree hierarchy schema. Any visual element cannot have more than a parent.
Assuming that every hierarchy level maps his own ring, I surely bet on the classical way to create such a composite UI. There's no doubt about the convenience of using the HierarchicalTemplates and ItemsControls, even it could be a complex task.
Moreover, I don't understand whether your goal is to have some kind of collapse, such an ordinary tree-view. In this case, avoiding the classical WPF approach would be a nightmare!
My solution is to create a custom panel, being able to arrange their children on a ring.
That's not all. It must be created both a custom Control and an ItemsControl. The first one will represent the ring-slice that has to be rendered, and the other just as the generator.
The control acting as item holder will have two properties: angle and radius. The thickness can be set apart.
The panel, calling MeasureOverride, must take in account the ring nesting, and set both the angle and radius of their children accordingly.
From my viewpoint, the holding control should derive from a ContentControl. That because you need to render the shape of the slice, and that task should be done by this control. Any particular embedded control (text, buttons, etc) can be placed inside as content.
Of course, all that is brainstorming. I'm not guarantee that is the best solution, nor that would work as is.
Hope it helps.
Cheers
I was wondering... I have a WinForms System.Windows.Forms.ListView with a bunch of ListViewItems that I'm drawing using the View.List style. Each ListViewItem has a "SmallIcon" that I fetch from the ListView's SmallImageList.
My problem is that the icons are showing too close to the border on the left. I've tried to change the bounds and the ListViewItem's Position property to no avail.
Is there anyway to have some kind of offset to ListViewItems?
The Win32 listview control doesn't have any setting to increase the space between the icon and the label (in any view, not just List). Setting ListViewItem.Position does nothing when the ListView is in List view.
A low-tech solution would be to simply prefix every ListViewItem's Text value with a single space. Slightly ugly, but oh so easy to do.
If you really want to have pixel level control, you will have to owner draw it. As always, if you are doing anything with a .NET ListView, ObjectListView makes owner drawing your items trivial.
As mentioned already, prefixing the text of all your items with a space is a super simple way to add padding. This has a pretty significant drawback, however. Once you do this, you lose the ability to find items in the ListView by simply starting to type their name while the ListView has focus.
Try adding white space to the left of your small images.
If you're using 16x16 images change to 24x16 for example by adding 8 white (or ListView Background color) pixels to the left.
If you are in ListView View LargeIcons then you can postion the text using item.position
A screenshot would be nice for an example to see exactly what you're after.
Funny thing... the Windows Explorer uses the ListView to display files and folders. i usually run my view in Report or Detail mode. i just switched it to List view mode and see the exact problem that you're describing! Yikes. Might be a bug with the Win32 object and that particular view type!
A quick workaround might be to use a Report style for the ListView with a single column or perhaps implement something yourself. The FlowLayoutPanel in .Net would work very nicely as a starting point for a custom list view.
As you are using the View.List style, I suspect you'll either need to implement some custom drawing or consider padding your images. You could also look at overriding the ListView control and manipulating it's bounds by overriding SetBoundsCore or SetClientSizeCore (or similar).
However, if the ListView were set-up for View.Details view, this could be done using the ListViewItem.IndentCount property:
The IndentCount property can be used
only when the View property of the
containing ListView is set to Details,
and the SmallImageList property of the
ListView is set. Source:MSDN
If you set the StateImageList property you can add a space of 16 px before the icons. I think you can adjust this additional space by loading an image with matching width as first entry into the StateImageList. But I have not tested this.
This thread discusses the opposite problem.
I'm trying to improve the graph drawing control that comes with Graph#. It's good, but things get out of hand when you start dragging nodes around. This is my first encounter with WPF, so this is probably a newbie question. :)
I have the GraphCanvas control which has nodes and edges on it. They can be dragged around which changes their coordinates, possibly making them negative. I would like to add scrollbars to the control which would allow to see how big the canvas really is.
To this end I'm thinking of putting the GraphCanvas inside a ScrollViewer. Which would be pretty easy and straightforward if not for one problem. I may not resize the GraphCanvas itself when a node is dragged outside the borders or this will mess up dragging bad. That is also the problem with the original control (check it out, it comes with a sample application).
It would be good if I could bind the scrollbar size/location to properties of the GraphCanvas, so that the ScrollViewer would not scroll anything physically, but just set the properties of GraphCanvas. That in turn would perform all actual calculations and scrolling.
How can this be done?
OK, I found it! Three easy steps:
Implement System.Windows.Controls.Primitives.IScrollInfo on your custom control;
Add your custom control to a ScrollViewer;
Set the CanContentScroll property on the ScrollViewer to True.
Voila!
Check out this link straight from MSDN. It talks about composing several controls into a single Composite Control:
WPF: Customizing Controls for Windows Presentation Foundation