Reputation: 2327
Lets say I have a list of custom control:
<ItemsControl>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ctrl:AutoCompleteTextBox />
</DataTemplate>
</ItemsControl.ItemTemplate>
</StackPanel>
These controls are autocomplete text boxes and I want the suggestions list to be rendered above the rest of the controls.
If I design my control like this:
<UserControl>
<StackPanel Orientation="Vertical">
<TextBox Name="Value" />
<ListView Name="Suggestions" />
</StackPanel>
</UserControl>
When I populate my ListView, the stackpanel grows and the other autocomplete are just shifted. I want them to be covered by the suggestions list.
I tried to use a Canvas with Panel.ZIndex property set to 2000, but the canvas is always rendered below the other items:
Here is the xaml:
<UserControl>
<StackPanel Orientation="Vertical">
<TextBox Name="Value" />
<Canvas Panel.ZIndex="2000">
<ListView Panel.ZIndex="2000" Name="Suggestions" />
</Canvas>
</StackPanel>
</UserControl>
I also tried to use a PopUp. It works well except that the popup is rendered on top of the screen, even if another application got the focus:
Here is the xaml:
<UserControl>
<StackPanel Orientation="Vertical">
<TextBox Name="Value" />
<PopUp IsOpen="false">
<ListView Name="Suggestions" />
</PopUp>
</StackPanel>
</UserControl>
I am open to any other solution, if it applies to my initial requirement.
Upvotes: 0
Views: 2696
Reputation: 2327
While the adorner's solution looks the proper way do do this, until I get it working, I found a workaround with the PopUp solution simpler than Daniel's one. It consists of handling the application desactivation (when switching to another application for example):
public AutoCompleteTextBox()
{
InitializeComponent();
var currentWindow = App.Current.MainWindow;
currentWindow.Deactivated += ApplicationDeactivated;
}
private void ApplicationDeactivated(object sender, EventArgs e)
{
this.HidePropositions(); // Here is all my stuff for hiding the suggestions list
}
Upvotes: 0
Reputation: 1897
You should use and Adorner. It needs more work, however you can always control when to display or hide the content. If the application goes background then you can hide the adorner programmatically.
When you use a control that is part of the visual tree the overlapping of the controls are defined by their order in the visual tree. If you use a container, which inherits from Panel you can fine tune this behavior with Z-Order. However Z-index has this ordering effect only for controls in the same container.
Adorners on the contrary are not part of the visual tree. They can be shown above everything. Unfortunatelly, working with them is more complicated than with regular controls. The framework does not really restrcit what you can or cannot do with an Adorner. There is no ultimate answer, since it depends on the application how the adorner should behave. For example if you use tabs, you might need to hide the displayed adorner/popup when the tab is changed. Therefore these kind of behaviours are left to the programmer.
Popups use adorners internally but there is less control about hiding or showing them. So, I suggest to use an adorner and customize its behavor for your exact purpose.
You can find more information about this issue HERE or HERE
UPDATE:
I just have checked what I was using when I had to do similar things. I used NonTopmostPoupup with some modifications. As far as I understand it does exactly what you are looking for. So I have to reconsider my point about the Popup control vs the Adorner :)
Upvotes: 3
Reputation: 587
You should be able to workaround this issue using the AirspacePopup since it "Is not always-on-top, but placed relative to the Window in which it is being placed" as mentioned in the original post.
You can see the full code and explanation in : AirspacePopup by Fredrik Hedblad
Upvotes: 0
Reputation: 394
Try to set the ZIndex of the User Control.
<UserControl Panel.ZIndex="your number">
<StackPanel Orientation="Vertical">
<TextBox Name="Value" />
<ListView Name="Suggestions" />
</StackPanel>
</UserControl>
Maybe you should also try to put your UserControl code at the bottom of your XAML code like this:
<!-- Your Code -->
<UserControl Panel.ZIndex="your number">
<StackPanel Orientation="Vertical">
<TextBox Name="Value" />
<ListView Name="Suggestions" />
</StackPanel>
</UserControl>
</Window>
Upvotes: 1