How to display multiple layers of controls in WPF? - wpf

I am trying to learn WPF and so far I love it. However, there is something missing or simply something that I don't understand. How can we display multiple layers of controls in WPF? Attached, the screenshot gives a good idea of what I am trying to do. I have a window and I want to display something else on top of it. How can I do that?

Placing two elements into the same row/column in a Grid simply overlays them. You can then use the Visibility on each element to show/hide them. So for example:
<Grid>
... row/column definitions
<Grid Grid.Row="0" Grid.Column="0">
... main content here
</Grid>
<Grid Grid.Row="0" Grid.Column="0" x:Name="grid2">
... overlaid content here
</Grid>
</Grid>
Now the overlaid content will appear over the top of the main content content. Setting grid2.Visibility to Visible/Hidden will show/hide your overlaid content.

I can think of two ways to achieve this effect (non rectangular semi transparent overlay on top of a window that extends behind the window's bounds).
First option, DON'T USE THIS IN PRODUCTION CODE (AllowTransparency is slow and very buggy) - Make the window larger then the actual content, set AllowsTransaprencey="True" so that the area "outside" of the window is transparent, now all you have to do for the popup is to add another visual in the same container as the "window" .
Second option, use a Popup, you will have to position your popup carefully, call SetWindowRgn via interop to make it non rectangular and call the Win32 API function that sets transparency value (sorry, don't remember the name at the moment) to make it semi-transparent.
The first option is easy to implement and will look better then the second option, but it's slower and you will run into all sorts of weird bugs (including crushes with some display drivers) - I know this from experience, when I switched the software I'm selling from AllowTransparency to SetWindowRgn 90% of the crush reports disappeared.
The second options requires a lot of native Win32 API calls but it should work.

I don't know much about WPF myself, but is the Panel.ZIndex attached property what you're after, perhaps?

you can use adorner layer to overlay . It's basically a rendering surface that overlays any adorned element.

You could achieve a similar effect by overlaying things in a grid (things just stack on top of each other if they're in the same cell), but my spider sense would tell me that that is just another window defined something like:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="SubWindow" Height="100" Width="100" WindowStyle="None" AllowsTransparency="True" Opacity="0.5" >
You could then show it in you main window by doing something like:
SubWindow sw = new SubWindow ();
sw.DoModal();

Not sure exactly what you are trying to accomplish but from my brief encounters with WPF, it seems like maybe you might accomplish what you need with the proper configuration of a parent\child relationship between your two windows. I recently so a basic 'hello, world' on Dr. Dobb's portal that may give you some direction.
Here's the link to the training tutorial video -- Dr. Dobb's TV you will just need to select the "Build a Standard WPF Application' video from the list...

Related

Generate array of WPF elements from XAML templates

I have a WPF program in which must draw an array of "bricks" onto a Canvas. There is a handful of different brick types, each of which looks different.
I want each brick type to be drawn using a fairly arbitrary fragment of XAML, e.g.
<Canvas> <!-- or some other per-brick container -->
<Rectangle Fill="Brown" Stroke="Gray" StrokeThickness="0.1" Canvas.Left="-1" Canvas.Top="-1" Width="2" Height="2" />
<Ellipse Fill="Blue" Canvas.Left="-0.8" Canvas.Top="-0.8" Width="1.6" Height="1.6"/>
</Canvas>
But I want the code-behind to clone this fragment many times, translating and rotating each copy into position.
This is similar to what an ItemsControl does, except I need to calculate my own brick positions. It also seems similar to what ControlTemplate does, but I don't understand that well enough to solve my problem.
Can anyone explain how it should be done?
There are several approaches but the one I'd go for is using view models and yes, an ItemsControl. You can specify what type of container the ItemsControl should use and pass a Canvas in, and then you can bind a collection of Bricks to the ItemsSource of the ItemsControl.
Then for each type of brick you can define a DataTemplate that specifies how that type should be rendered. If the items have properties such as X and Y you can bind those to the Canvas.Left and Canvas.Right properties in the DataTemplate and off you go...
A good example of what I mean is https://stackoverflow.com/a/1030191/430661 (the most upvoted answer, not the selected one), except there the item template is specified inline instead of through DataTemplates. Just leave the itemTemplate empty and let the framework select the proper DataTemplate based on type.
Now on the other hand if you expect to have many bricks on screen, or perform complex animations on them, or anything like that... this probably won't perform well enough for that kind of scenarios. But then you're probably better off not using WPF for that anyway...
Let me know if you need more help and I can throw together a sample for you.

how to use xaml magic

I have problems figuring out where to use what xaml keywords because its hard to figure out what hierarchy it wants. It seems there is some grand design on how and where to use attributes, properties or child nodes.
<Node Attribute="True">
<Node.Property />
</Node>
I found this beautiful page explaining all the ribbon menu properties, but have no idea how to use them in xaml. After half an hour of searching and trying everything I managed to get an Icon to show in the ribbon menu button.
What is the logic behind this all and how to figure out what to use where?
How to merge the ribbon menu with the application bar (the top bar on most windows applications)? So I get a nice Ribbon Application Menu, like in the example.
Is there a way to turn off xaml background compliation? I'd sacrifice Intellisense for this.
Because the xaml editor performance is abysmal, the are many suggestions for this, but none working so far.
Edit:
I know the xaml syntax, but there's no hint on what hierarchy to use. So if I find the object I want to use (because they are all available) it will only say I'm using the wrong object, it should ask for the kind of object it wants to be in.
Also in normal programming when you use a reference you can always use all classes in it. With xaml we must suddenly know what reference our class came from, also it won't find the reference for you, you either have to try all references to see if they have a certain class or find a code example.
Good questions. Its a little hard to get a feel for exactly what you're asking for in your #1 question, but I'll take a brief stab at that one. I do have an answer for your #2 question. I do not have an answer for your #3.
"1. What is the logic behind this all and how to figure out what to use where?"
Like Clemens mentioned, the XAML Overview does a pretty good job at explaining things.
I'm guessing that one of the main things that you're asking about is basically "when do you use attribute syntax vs property element syntax". From that doc:
For some properties of an object element, attribute syntax is not possible, because the object or information necessary to provide the property value cannot be adequately expressed within the quotation mark and string restrictions of attribute syntax. For these cases, a different syntax known as property element syntax can be used....
Now about this part of your question...
"Also in normal programming when you use a reference you can always use all classes in it. With xaml we must suddenly know what reference our class came from, also it won't find the reference for you, you either have to try all references to see if they have a certain class or find a code example."
If part of your question is more about how can you more-easily handle your XAML (or more appropriately xmlns) namespaces so that it is easier to get references ironed out in your XAML, there is a technique that you may find useful. It lets you consolidate namespaces so that you can use fewer XAML namespace prefixes (or even no namespace prefixes if you take this technique to its extreme).
"2. How to merge the ribbon menu with the application bar (the top bar on most windows applications)? So I get a nice Ribbon Application Menu, like in the example."
Essentially it seems that you're asking how to: (a) extend the window chrome area (the Aero glass area) down into the client part of the window (the part that your application normally gets to put things) and (b) extend the client part of the window up into the window chrome area. If you can do both of these things, then you can end up with something that looks like Microsoft office products or modern web browsers. Fortunately there is the WPF Shell Integration Library which helps you do both of these things. I found this blog and this blog (and the source code they offer) good guides for getting started with using the WPF Shell Integration Library.
Using this library, I was able to make this window (all but the Aero color changing abilities which is a whole other topic). Notice that both of qualities I mentioned are working here (the TabControl is being display up in the normal window chrome top bar area and the window chrome Aero glass is being displayed down in the normal client area):
Here's my take
1) What is the logic behind this all and how to figure out what to use
where?
Whatever you can fit between "" can go inline like:
<TextBlock Text="{Binding Name}" />
Whatever can't, go the element way:
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} ({1})">
<Binding Path="Name" />
<Binding Path="Gender" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
2) How to merge the ribbon menu with the application bar (the top bar on
most windows applications)? So I get a nice Ribbon Application Menu,
like in the example.
You'll find more or less complicated mumbo jumbo around google, this is the essence of it:
<Window ...
WindowStyle="None" AllowsTransparency="True" Background="Transparent"
...>
<!-- Fill it up with a PNG image if you want to play with transparency -->
</Window>
Then make the ribbon the top element, and re-create Close/Maximize buttons
3) Is there a way to turn off xaml background compliation? I'd sacrifice
Intellisense for this.
Yep, it's called Notepad++

positioning of elements in xaml

I have 2 ListPicker's.
For example:
<toolkit:ListPicker FullModeItemTemplate="{Binding lpkFullItemTemplate}" ItemTemplate="{Binding lpkItemTemplate}"
x:Name="lpkIcon">
</toolkit:ListPicker>
<toolkit:ListPicker FullModeItemTemplate="{Binding lpkFullItemTemplate}" ItemTemplate="{Binding lpkItemTemplate}"
x:Name="lpkWhen">
</toolkit:ListPicker>
This Listpickers are located near. When i am click on first listpicker it shows the menu, but its covered by the second listpicker.
I tried to disable the visibility of second listbox when i click on first, but i think everything can be done through the xaml.
sorry for really stupid question and thanks.
I'm presuming you're talking about when the ListPicker is NOT in full mode (which opens in full screen).
How the two list pickers will interact visually will ultimately depend on the type of panel they're both contained in. So I can't give you a better answer unless I know which Panel you're using.
I use a lot of List Pickers in one of my apps To Do Today and my best suggestion is to use a Stack Panel wrapped with a Scroll Viewer.

WPF Drawing on a ListBox

In a ListBox derived CustomControl I need to draw lines joining ListBoxItems that are layed out in a Canvas ItemsPanel.
I can achieve this by having class ListBoxLines : UIElement that does drawing in OnRender and then including that object in my ListBox ControlTemplate (but to do that I need to pipe the listbox contents to that class...)
<ControlTemplate TargetType="{x:Type p:NetworkVisualization}">
<Grid>
<p:ListBoxLines/>
<ItemsPresenter/>
</Grid>
</ControlTemplate>
Im just wondering if there is an easer way. Id really just like to add my draw code directly to my ListBox derived class but if I do that it seems to draw UNDER the listbox canvas white background.
Is there any way to to custom listbox drawing directly in my derived listbox class?
EDIT: The motivation for this question is a custom control to display nodes and linkstrengths of a wireless mesh network as in the image below:
EDIT: Additional issue: The OnRender code for ListBoxLines (the node links) is cached - how to force a redraw of this when a node is dragging? Ideally i want to build the cache with the all lines except for the currently dragging nodes lines and only redraw while dragging the lines to that node - not sure how to go about that.
Thanks for updating the question - from the original description we were on completely different pages.
Personally I would not implement a control like this, as I know from prior experience that it is not easy task. In the last two three occasions where I have needed charting I have used middle-ware solutions.
The argument for middleware is an easy case to make:
It will save you significant development time.
You will get results quicker, allowing you focus on your specific requirements.
Even if you choose a commercial provider, the time saved equates to money.
I recently evaluated charting middleware options for a project less than 5 months ago so I can tell your directly that for a WPF application the best libraries are:
Mindscape Diagrams 2 (Commercial)
Chart# (Codeplex Project, Microsoft Public License)
I have used both products for studio applications (internal, however released as if the users were clients).
...
Take a look at the above solutions, come back with further questions (if any) and then if you still want to write your own I will at the very least point you in the direction and resources to do.
A side note, you say that you like the selection part of the ListBox - did you know that the selection functionality is actually supplied by the Selector base class?

How to create databinding over two xaml files?

I am trying to come to a working understanding of how databinding works, but even after several tutorials I only have a basic understanding of how databinding works. Thus this question might seem fundamental to those more familiar with silverlight. Even if it is trivial, please point me to some tutorial that deals with this problem. All that I could find simply solved this via adding the data binding on a parent page.xaml (that i must not use in my case).
For the sake of this example let us assume, that we have 5 files:
starter.cs
button1.xaml + codeBehind
button2.xaml + codeBehind
The two buttons are generated in code in the starter(.cs) file, and then added to some MapLayer
button1 my_button1 = new button1();
button2 my_button1 = new button2();
someLayer.Children.Add(my_button1);
someLayer.Children.Add(my_button2);
My aim is to connect the two buttons, so that they always display the same "text" (i.e. my_button1.content==my_button2.content = true;). Thus when something changes my_button1.content this change should be propagated to the other button (two way binding).
At the moment my button1.xaml looks like this:
<Grid x:Name="LayoutRoot">
<Button x:Name="x_button1" Margin="0,0,0,0" Content="{Binding ElementName=x_button2, Path=Content}" ClickMode="Press" Click="button1_Click"/>
</Grid>
But everthing that i get out of that is a button with no content at all, it is just blank as the binding silently fails.
How could I create the databinding in the context I described? Preferably in code and not XAML ;)
Thanks in advance
The chunk of documentation you need to read is this: XAML Namescopes
Your button1 xaml has a binding looking for an element with the name "x_button2". However in a real application there can be many controls which in turn have nested controls. All of these controls have all manner of UI elements some of which may have names.
It would be impossible to get anything done if all names throughout the entire application had be unique. Yet that would need to be true if it were for your button1 to be able to hunt down the existence of another control somewhere in the visual tree outside of that which it actually knows (its own xaml).
Hence each loaded Xaml document exists in its own "namescope" and the search for other elements with other names is limited to that "namescope".
The are various solutions to this problem depending on what you real requirements are as opposed to the simplified problem in your question.
Typically you give each of your controls a DependencyProperty to which the inner button Content property binds. In "MapLayer" as call it, could then bind the propert on one of your button controls to the other.

Resources