WPF ComboBox - If expanded, stays on top of all windows - wpf

I have a WPF form with ComboBox on it. If I expand my combobox, then open an app such as Notepad or any other, the app will cover my WPF form but the expanded ComboBox portion will still be on top. So it appears as the Notepad app is between the WPF form and its expanded portion of ComboBox (the combo box dropdown). It looks like the ComboBox will show its expanded dropdown always at the top of z-order.
This is causing few other issues such as beeing unable to close the WPF form.
This is simply wrong.
Above:
z-1 is z-order of my WPF form with expanded ComboBox (but note that the expanded area is on top of applications opened and overlapping the WPF form
z-2 is order of Notepad application opened and overlapping my WPF form with the ComboBox on it (again, you can see that Notepad overlaps WPF form but the ComboBox expanded dropdown overlaps Notepad. It should be behind Notepad, not in front of it)
z-3 is the expanded dropdown of my ComboBox located on WPF form with z-1 order
My ComboBox is part of UserControl and its xaml is like this
<ComboBox Name="MyComboBox"
ItemsSource="{Binding ItemsSet}"
DisplayMemberPath="Name"
SelectedValuePath="Name"
SelectedItem="{Binding Path=SelectedItem}"
BorderBrush="Green"
BorderThickness="2">
</ComboBox>
How do I prevent the issue in the provides screenshot?

I understand that the behavior is in most cases "wrong"; when would you really want a dropdown to stay open if focus is lost on the current application? However, as I mentioned in my comment, that is the designed behavior of the Popup control. A WPF combobox under the hood is actually a ToggleButton with a Popup control that is set to open when the ToggleButton is toggled. So... the way to prevent the issue you're seeing is to prevent the Popup control from staying on top of all applications.
There's a StackOverflow question for that :)
Popup always stays on top
One of the answers actually has code snippet with a derived/custom popup control that uses user32.dll to prevent the undesired behavior.
So ok great, that's how you fix a Popup, but how do you fix a ComboBox? You simply have to override the default ControlTemplate to use the fixed-non-top-most Popup control instead of the standard WPF Popup.

I "fixed" this by setting the WPF form containing my ComboBox as TopMost="True" in its xaml. Not perfect fix but at least removes the stupid look and all other problems it leads to I discovered. I cannot believe that MS made this default behavior, it is plain stupid.

Related

Multiline Combobox Control in WPF

I would like to build a multiline combobox in WPF. This would be similar to label control wherein the width of control will grow such that entire selected text is visible. The text displayed can go over next line if there is no enough space available on current line.
I tried few things around control template of combobox. But still no success.
Below is sample screenshot of how it should look like!
Any pointers?
Thanks,
Sambhaji
As per my understanding setting the control template for this particular scenario would be a tedious job. I would have created a TextBlock and tried setting the event triggers which will open a container on mouse hover or click event.

Why Popup part of combobox is resizable in one context and not in the other?

I have a wpf cusotm control derived from combobox System.Windows.Controls.ComboBox the control template is redefined and the popup (PART_Popup) contains a DataGrid and some other control. I use it in two places - in TabControl(,Grid) and in a Window(Grid,,Grid). When the DataGrid is resized either by dragging columns or from code the behavior is different: in window the Popup resizes in TabControl Popup remains the same and a scrollbar appears if necessary.
I need to know what can cause such difference.
Edit
Datagrid is has HorizontalAlignment="Stretch"
I find it. By mistake there was
Popup.Width=Me.Width
instead of
Popup.Width=Me.ActualWidth
This caused resizability in case when the Me.Width was not set.

wpf validation refresh between tabbed pages

I'm getting there with this WPF validation, IDataErrorInfo, INotifyPropertyChange stuff, but new issue on refresh. I have a window with a bunch of controls on it. I have a tabbed page interface and for simplicity have 2 pages... 5 controls on each.
I start to "Add" a record, so all fields are blank. Ex: 3 of the fields on the first page that require validation are properly flagged as red border to indicate they are required... no problem.
Now, I click on to page 2 and immediately back to page 1. The red borders are all gone. They don't reappear red unless I explicitly tab through them to re-focus them, lose focus and force it to do its lostfocus / property changed validation via IDataErrorInfo.
First, any explanation WHY WPF is losing what the first page looks like just because it has to change page 1's visiblity to show page 2, and then back to page 1.
Second, suggestions on how to force the controls to be properly refreshed with the red border indicating they are required.
Thanks
Just put the controls you validate inside an AdornerDecorator an it will work fine ;)
<TabItem>
<AdornerDecorator>
<Grid>
<TextBox>
</TextBox>
...
</Grid>
</AdornerDecorator>
</TabItem>
If I recall correctly, the default error validation markers for controls are just red boxes overlaid over the top of the control, not part of the control itself, so the visibility of that overlay does not persist if the control is hidden. You might try changing the control template to incorporate a red border / label directly as part of the control, and that issue might be cleared up.
To force all your bindings to refresh (and therefore their validation) all you need to do is call RaisePropertyChanged again for any property you want to re-validate. It's a little wasteful, but you can just call RaisePropertyChanged with an empty string as parameter, and it will raise for all properties in the viewmodel.

WPF: How to change button content (text) with a double click at runtime

I have a button in WPF, I want to change the text when I double click on it, that is I want the cursor to appear and type the text that is to be shown as the content (similar behavior as when pressing F2 on a desktop shortcut).
I guess I could detect a double click and then show a textbox with a transparent background, that will get me the cursor, type the text in this new textbox, set it to the buttons content and delete the textbox, but that doesn't seem the right way to do it.
I guess what I had in mind, is that I am developing a diagramming tool using shapes. Since shape doesn't derive from ContentControl I cannot put a text box inside it, and I want to simulate this behavior. I was thinking of making a custom control but that might be too much work for this, and am not quite familiar with this topic yet. I guess another approach would be to use an adorner (maybe a border) and since it derives from contentcontrol I can do the same thing as joe suggested. any ideas?
Another thing I could do would be to put the shape in a grid, and then put the textbox on top of the shape, but I am not sure how would that be as a design principle, and also I don't know if the hit testing would only be on the shape or the grid.
Since this is WPF, you can put a TextBox inside your Button with no trouble. If you don't want the textbox to have a border and white background -- i.e., if you want it to look like you're just typing directly into the button -- then you could remove them by setting BorderWidth to 0 and Background to Transparent.
What you probably want to do is have your Button's Content be a Grid that contains both the normal content (probably a TextBlock) and the TextBox, with the TextBox initially hidden (Visibility = Collapsed). Then when you get the double-click event, you would hide the TextBlock and show the TextBox.
<Button>
<Grid>
<TextBlock Name="buttonText">Double-click to rename me</TextBlock>
<TextBox Name="buttonEdit" Visibility="Collapsed" MinWidth="100"/>
</Grid>
</Button>

Alternative to FindAncestor RelativeSource in Silverlight 4 to bind to a property of the page

FindAncestor RelativeSource only supports 'Self' and 'TemplatedParent',
but I have to bind the width of a popup to the width of the page.
Giving the page a name causes problems because sometimes it will
throw exceptions saying a control with that name is already present in the visual tree.
<Popup IsOpen="True"
Width="{Binding ElementName=BordPage, Path=Width}"
Height="{Binding ElementName=BordPage, Path=Height}">
Background information:
I'm using a SL4 navigation based application here. BordPage is a navigation page,
which I'm using multiple times within the application. So giving it a name in the page itself is not really a good idea,
but I don't know how else I can bind to the width and height of the page.
What I'm trying to do is have a black border (with opacity 0.8) cover the entire screen,
(including the controls of the MainPage). Then on top of that I want to display some other controls.
Since the application is touch controlled, providing the user with a ComboBox to select a value doesn't really work wel. Instead I want to show this black overlay window with a listbox taking up most of the screen so the user can simply touch the value he wants with a single click.
Update: I just realized I can use the ChildWindow class to do this.
But my original question remains.
My general solution for this problem is by writing a custom behavior. It's not a pure XAML solution but it gives you a lot more flexibility.
Create a behavior that searches up the VisualTree to find the right item and then have it set the width of the Popup correctly.
It may be a little more complicated than a straight binding but it avoids all the naming issues.
Put the following in the constructor of your control so you can avoid naming it:
DataContext = this;

Resources