I want to make my tabControl a little smarter to save some screen real estate: Don't show tab header if there is only one tab and show tab headers if there are two or more tabs.
I know that you can hide the tab header completely as suggested at How do I create a TabControl with no tab headers?. The problem with this approach is that, once hidden, I cannot show the tab header again. Or did I miss something?
Crediting the guy that actually came up with the idea:
using System;
using System.ComponentModel;
using System.Windows.Forms;
public class WizardPages : TabControl {
private bool tabsVisible;
[DefaultValue(false)]
public bool TabsVisible {
get { return tabsVisible; }
set {
if (tabsVisible == value) return;
tabsVisible = value;
RecreateHandle();
}
}
protected override void WndProc(ref Message m) {
// Hide tabs by trapping the TCM_ADJUSTRECT message
if (m.Msg == 0x1328) {
if (!tabsVisible && !DesignMode) {
m.Result = (IntPtr)1;
return;
}
}
base.WndProc(ref m);
}
}
Grave digging a bit but I know of another solution. I have no idea where it came from but here it is:
In form load: (VB.NET)
Tabcontrol1.Region = New Region (New RectangleF(TabPage1.Left, TabPage1.Top, TabPage1.Width, TabPage1.Height))
Where TabControl1 is the name of your tab control and TabPage1 is the name of the first tab page in that control.
If you wanted to make it usable as a routine then you could do something like this:
Public Sub hideTabs(ByVal TC as TabControl)
TC.Region = New Region(New RectangleF(TC.TabPages(0).Left,TC.TabPages(0).Top, TC.TabPages(0).Width, TC.TabPages(0).Height))
End Sub
It is that easy. What is nice about this is that the headers are not shown at runtime but they are visible at design time.
To expand on Hans's answer:
I wanted to have the TabControl able to hide tabs in design time too, but then there was a problem, that once you hide the tabs, there is no way to select the TabControl to turn them on again, so i created a custom TabPage, that is able to control this property
Imports System.Windows.Forms
Public Class NoHeaderTabPage
Inherits TabPage
Public Property ShowTabs() As Boolean
Get
Return CType(Me.Parent, NoHeaderTabControl).ShowTabs
End Get
Set(ByVal value As Boolean)
CType(Me.Parent, NoHeaderTabControl).ShowTabs = value
End Set
End Property
End Class
Related
I want to make my app to be accessible (make my app exposed for screen readers, which are UI automation client, like "Narrator").
I got some ContentControl that when it got keyboard focus, I'm showing a tooltip (taking it from the Tooltip property of this ContentControl). It's a control that used in many ways, for example it can be used like that:
the Content of this ContentControl is a question mark icon image, and the ToolTip is the help text...
Here is a concept code:
class AutoTooltipOnFocus : ContentControl
{
public AutoTooltipOnFocus()
{
this.GotKeyboardFocus += OnGotKeyboardFocus;
}
private void OnGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs keyboardFocusChangedEventArgs)
{
bool automationListens = AutomationPeer.ListenerExists(AutomationEvents.AutomationFocusChanged);
if (automationListens)
{
// don't show tooltip because GetNameCore of MyAutoPeer will represent the ToolTip value
return;
}
// show tooltip (by reading the ToolTip value of this AutoTooltipOnFocus)
}
protected override AutomationPeer OnCreateAutomationPeer()
{
return new MyAutoPeer(this);
}
}
class MyAutoPeer : FrameworkElementAutomationPeer
{
private AutoTooltipOnFocus _owner;
public MyAutoPeer(AutoTooltipOnFocus owner)
: base(owner)
{
}
protected override string GetNameCore()
{
return GetToolTipValueFromOwner();
}
private string GetToolTipValueFromOwner()
{
// just for the simplicity of the example, I return this:
return ToolTipService.GetToolTip(_owner).ToString();
}
}
Narrator, for example, reads the textual representation of the Content (let's say the property AutomationProperties.Name of the image is set to "help icon") and then says "Tooltip: some help text".
I don't want to count on the tooltip been read by all the screen readers (correct me if I'm wrong thinking some of them don't read Tooltips), so I made my GetNameCore return the ToolTip content so that I know it would be read necessarily, and I prevented the appearance of the tooltip (at OnGotKeyboardFocus handler) in order to prevent double reading of the same help text.
The problem is that: I thought that asking AutomationPeer.ListenerExists(AutomationEvents.AutomationFocusChanged) tells me that UI automation is listening to my app, but when narrator is not running, this method returns "false" and the rest of the times it returns true, so no tooltip appears when no one using screen reader, so I need to know what is the way to indicate whether UI automation client is running and listening to my app.
Maybe there is a workaround by adding some code to my custom AutomationPeer.
Thanks for giving your time!
I have a user control that is a spinning "wait" graphic. I've added it to a form and I set-up a convention in Caliburn.Micro using the code from this thread
I then created a property following the naming convention and named this user control accordingly:
<uc:LoadSpinner x:Name="Authenticating" />
My property looks like this:
protected bool _authenticatingIsVisible = false;
public bool AuthenticatingIsVisible
{
get { return _authenticatingIsVisible; }
set
{
_authenticatingIsVisible = value;
NotifyOfPropertyChange(() => AuthenticatingIsVisible);
}
}
I can see the control get bound and when the form starts up, the spinner is invisible. However, when I set it visible it still doesn't appear. To simplify things and test the binding I then created a rectangle on the form and named it the same way. It appears/disappears as expected. So it seems like it's either something specific to a user control or animations.
I also tried wrapping the user control inside of a Border control and naming it the same way (the idea was if normal controls worked, then the contained user control should appear/disappear when the Border does). Nope.
Why isn't this working?
Theodosius Von Richthofen is correct. You want to use Visibility not bool. Try this:
protected Visibility _authenticatingIsVisible = Visibility.Hidden;
public Visibility AuthenticatingIsVisible
{
get { return _authenticatingIsVisible; }
set
{
_authenticatingIsVisible = value;
NotifyOfPropertyChange(() => AuthenticatingIsVisible);
}
}
I'm using Caliburn.Micro and Modern-UI in a WPF application. On a "page" inside the modern-ui framework (which is a UserControl), I am trying to use a Conductor to switch the current view. Here is what I've got so far:
NOTE: Namespaces removed from source for brevity
XAML of "page" inside modern-ui window
<UserControl x:Class="ShellView">
<ContentControl x:Name="ActiveItem" />
</UserControl>
Source for ShellViewModel (the conductor)
[Export]
public class ShellViewModel : Conductor<IScreen>.Collection.OneActive
{
private readonly Test1ViewModel m_TestView1;
private readonly Test2ViewModel m_TestView2;
public ShellViewModel()
{
this.m_TestView1 = new Test1ViewModel();
this.m_TestView2 = new Test2ViewModel();
this.ActivateItem(this.m_TestView1);
}
}
The XAML for Test1View doesn't have anything in it right now, just normal UserControl stuff.
Source for Test1ViewModel
public class Test1ViewModel : Screen
{
protected override void OnActivate()
{
//This DOES NOT show or fire, I even put a breakpoint to double check
Debug.Print("This should show in output");
}
}
when ActivateItem is called, OnActivate does not fire at all. I even tried calling ConductWith(this) on the view model Test1ViewModel in the conductor but that didn't work. I am using Modern-UI which might be important because this same thing works in a different project that is not using Modern-UI. Oh and when ActivateItem is called, the appropriate view does show on the screen (I added some buttons for verification that the view does change).
Any ideas as to why the UserControl will show in the ContentControl after calling ActivateItem but OnActivate does not fire at all?
One more thing... This might also have something to do with it, but if it does I don't know why or how to fix it. I'm using this class to make the view first Modern-UI work well with Caliburn.Micro's model first approach.
internal class ModernContentLoader : DefaultContentLoader
{
protected override object LoadContent(Uri uri)
{
object content = base.LoadContent(uri);
if (content == null)
return null;
// Locate the right viewmodel for this view
object vm = ViewModelLocator.LocateForView(content);
if (vm == null)
return content;
// Bind it up with CM magic
if (content is DependencyObject)
ViewModelBinder.Bind(vm, content as DependencyObject, null);
return content;
}
}
I went and downloaded the source for Caliburn.Micro and debugged the whole thing like I should have done from the start.
Turns out, because of the way Modern-UI handles navigation the Conductor (unless it's the main shell view attached to the main window) doesn't get activated. In other words, it never knows that it's being shown and the source for Caliburn checks to make sure the Conductor is active before it will allow activating a new view. For some reason the view is displayed just fine but the View Model (Screen) never gets activated or instantiated. In my case it is instantiated because of the Modern-UI+Caliburn.Micro view binding hack.
I did get it to finally work, so if anyone is interested, this is how to get ActivateItem with a Conductor to work inside Modern-UI.
Add the following line of code to your Conductor's constructor or the Modern-UI method OnNavigatedTo
ScreenExtensions.TryActivate(this);
This is part of Caliburn-Micro and will allow your Conductor to activate items properly. If you're using it inside the OnNavigatedTo you might want to add this line to your OnNavigatedFrom method:
ScreenExtensions.TryDeactivate(this, true);
I have a MDI-Parent Form with many ChildForms, when I want to add a control on my Parent form, Child form appears under the control, For example I want to add a groupbox and a PictureBox on MDIParent Form, but when I call the Child Form it appears Under these controls.
frmChildForm1.TopMost=true doesn't works either.
I have attached a photo for more description.
What can I do?!
but I want to have an Image as Background
That's possible, you can set the BackgroundImage property of the MDI client control. The only obstacle is that you cannot directly get a reference to that control. You have to find it back by iterating the form's Controls collection. Like this:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
foreach (Control ctl in this.Controls) {
if (ctl is MdiClient) {
ctl.BackgroundImage = Properties.Resources.Lighthouse;
break;
}
}
}
}
Where Lighthouse was a sample image I added as a resource. Change it to use your own. Another common technique is to subscribe the Paint event for that control and draw whatever you want. A gradient is a common choice.
I'd like the main menu in my WPF app to behave like the main menu in IE8:
it's not visible when the app starts
pressing and releasing Alt makes it visible
pressing and releasing Alt again makes it invisible again
repeat until bored
How can I do this? Does it have to be code?
Added in response to answers submitted, because I'm still having trouble:
My Shell code-behind now looks like this:
public partial class Shell : Window
{
public static readonly DependencyProperty IsMainMenuVisibleProperty;
static Shell()
{
FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();
metadata.DefaultValue = false;
IsMainMenuVisibleProperty = DependencyProperty.Register(
"IsMainMenuVisible", typeof(bool), typeof(Shell), metadata);
}
public Shell()
{
InitializeComponent();
this.PreviewKeyUp += new KeyEventHandler(Shell_PreviewKeyUp);
}
void Shell_PreviewKeyUp(object sender, KeyEventArgs e)
{
if (e.SystemKey == Key.LeftAlt || e.SystemKey == Key.RightAlt)
{
if (IsMainMenuVisible == true)
IsMainMenuVisible = false;
else
IsMainMenuVisible = true;
}
}
public bool IsMainMenuVisible
{
get { return (bool)GetValue(IsMainMenuVisibleProperty); }
set { SetValue(IsMainMenuVisibleProperty, value); }
}
}
You can use the PreviewKeyDown event on the window. To detect the Alt key you will need to check the SystemKey property of the KeyEventArgs, as opposed to the Key property which you normally use for most other keys.
You can use this event to set a bool value which has been declared as a DependencyProperty in the windows code behind.
The menu's Visibility property can then be bound to this property using the BooleanToVisibilityConverter.
<Menu
Visibility={Binding Path=IsMenuVisibile,
RelativeSource={RelativeSource AncestorType=Window},
Converter={StaticResource BooleanToVisibilityConverter}}
/>
I just came across this problem myself. I tried hooking into the PreviewKeyDown event, but found it to be unreliable. Instead I found the InputManager class where you can hook into the EnterMenuMode from managed code. The manager exposes two events, for enter and exit. The trick is to not collapse the menu, but set it's container height to zero when it is to be hidden. To show it, simply clear the local value and it will take its previous height.
From my TopMenu user control:
public TopMenu()
{
InitializeComponent();
InputManager.Current.EnterMenuMode += OnEnterMenuMode;
InputManager.Current.LeaveMenuMode += OnLeaveMenuMode;
Height = 0;
}
private void OnLeaveMenuMode(object sender, System.EventArgs e)
{
Height = 0;
}
private void OnEnterMenuMode(object sender, System.EventArgs e)
{
ClearValue(HeightProperty);
}
I'd try looking into handling the PreviewKeyDown event on your window. I'm not sure if pressing Alt triggers this event or not, but if it does, then I'd toggle a bool which is bound to the visibility of the main menu of the window.
If PreviewKeyDown doesn't work, I'm not sure what else to try. You could look into getting at the actual Windows messages sent to your window, but that could get messy very quickly.
It would be better to use GetKeyboardState with VK_MENU to handle both left and right Alt, to mimic the behavior of IE / Windows Explorer (Vista+) you'll need to track the previously focused element to store focus, on a VK_MENU press whilst the focused element is within your main menu. You also want to be doing this work on PreviewKeyUp (not down).
See my answer to the following thread:
How to make WPF MenuBar visibile when ALT-key is pressed?
There I describe how to solve your problem with the class InputManager (from namespace System.Windows.Input).
You can register the classes events EnterMenuMode and LeaveMenuMode.