I am having trouble causing an 'autohide' dock to appear programmatically.
Couldn't find any answer around the net, though the following SO Question suggested that .Show() should have done the trick
I've tried this on the latest NuGet version of the code.
My test code is below.
Anyone know how to do it? or what I'm doing wrong?
Update: apparently this is a bug in 2.7.0, I've opened an issue for it with the project.
#roken's answer is an excellent workaround, so I've updated the code below to reflect it.
My test Code
Create a simple Visual Studio Windows Form application, and replace the main form's source file content with this code:
using System;
using System.Windows.Forms;
using dps = WeifenLuo.WinFormsUI.Docking;
namespace testDockPanel
{
public partial class Form1 : Form
{
private dps.DockPanel dockPanel;
private dps.DockContent dc;
private Control innerCtrl;
public Form1()
{
InitializeComponent();
dockPanel = new dps.DockPanel();
dockPanel.Dock = DockStyle.Fill;
dockPanel.DocumentStyle = dps.DocumentStyle.DockingWindow;
toolStripContainer1.ContentPanel.Controls.Add(dockPanel);
dc = new dps.DockContent();
dc.DockPanel = dockPanel;
dc.DockState = dps.DockState.DockRightAutoHide;
innerCtrl = new WebBrowser() { Dock = DockStyle.Fill };
dc.Controls.Add( innerCtrl );
This is the part of the code that didn't work:
// This SHOULD show the autohide-dock, but NOTHING happens.
dc.Show();
I've replaced it with #roken's suggestion and it now works:
dockPanel.ActiveAutoHideContent = dc;
innerCtrl.Focus(); // This is required otherwise it will autohide quickly.
}
}
}
To show a hidden autohide content, you can set the active auto content directly:
dockPanel.ActiveAutoHideContent = dc;
It's not clear to me if the inability to activate the content via Show() is a bug that has been introduced. If you have a free moment could you try running the code you provided against version 2.5.0 to see if Show() activates the content like you expect?
Related
I have derived class in my WPF project like this
public class NetworkCommunicator : WindowWallet
{
System.Windows.Threading.DispatcherTimer listenerTimer = new System.Windows.Threading.DispatcherTimer();
public NetworkCommunicator()
{
listenerTimer.Tick += new EventHandler(listenerTimer_Elapsed);
listenerTimer.Interval = new TimeSpan(0, 0, 1);
listenerTimer.Start();
}
private void listenerTimer_Elapsed(object sender, EventArgs e)
{
base.AddLogContent("some text");
}
}
And the parent class that is also an currently opened window.
public partial class WindowWallet : Window
{
NetworkCommunicator netCommunicator;
public WindowWallet()
{
InitializeComponent();
netCommunicator = new NetworkCommunicator();
}
public virtual void AddLogContent(string s)
{
textBoxNetworkLog.AppendText(Environment.NewLine + s);
}
}
And this is the XAML code of the textBoxNetworkLog
<TextBox x:Name="textBoxNetworkLog" Height="153" Margin="10,0,10.4,33.4" TextWrapping="Wrap" VerticalAlignment="Bottom" VerticalScrollBarVisibility="Auto" AcceptsReturn="True" Text="AnoBIT Network Log started..." IsReadOnly="True" TextChanged="textBoxNetworkLog_TextChanged"/>
The problem is that the textBoxNetworkLog.Text property doesn't update and I can't see the changes in the opened WindowWallet. I made some debugging and I can see that the textBoxNetworkLog.Text is updating every second and the property is changing as expected in the Locals window when I debug my code step by step (every second there is new line of some text as expected). But that's only during the debugging and I see zero changes in the opened WindowWallet.
I know that
The listenerTimer is running
The AddLogContent executes
When I type something in the opened WindowWallet into the textBoxNetworkLog, the textBoxNetworkLog.Text property in the Locals does not (obviously) sync with the text I typed in.
When I try different object other than textBoxNetworkLog in the AddLogContent method, the text doesn't change in the Window aswell
I have only one WindowWallet opened and only one instance of the NetworkCommunicator created
I am doing this on the WPF framework
The textBoxNetworkLog_TextChanged contains literally nothing, so there is no problem there
It just looks like the method doesn't change the text of the textBoxNetworkLog that is in the CURRENT INSTANCE of the opened Window or something like that. Please help me, I am hopeless. Thanks
EDIT: I guess it just doesn't refer to the current instance which I have opened now. I solved it with this one line (maybe there will be more in need in a case there will be more WindowWallet instances opened
WindowWallet CurrentInstanceWallet = Application.Current.Windows.OfType<WindowWallet>().FirstOrDefault();
Solved it by myself. This one line will do the trick.
WindowWallet CurrentInstanceWallet = Application.Current.Windows.OfType<WindowWallet>().FirstOrDefault();
If there are gonna be more instances of WindowWallet's it will maybe need to modify a little bit.
I am creating my textbox programmatically in a console application that builds a form window on the fly. I am trying to get Input boxes such as the textbox to show up invisible but still allow the user to input data such as username and password or any other customisation fields I provide. This is for a game launcher and I am attempting to make it NOT look like a windows component.
I have tried some of the solutions on the post below.
Transparency for windows forms textbox
EDIT: As you can see above I have already cited that this does not solve my issue. I do not use the form designer as it has a nasty habit of deleting my code because I presume "It knows better".
The Accepted answer for that does not work for me as I do not use the form designer and InitializeComponent();
Does not work it just tells me that it is not a function of the component.
I have gotten as far as this.
using System.Windows.Forms;
namespace Launcher_Namespace
{
public class TransparentTextBox : TextBox
{
public TransparentTextBox()
{
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
}
}
}
And in the main body of code that initialises fields
//Initialise Inputs
_username = new TransparentTextBox();
_username.Bounds = new Rectangle(120, 10, 120, 21);
_username.BackColor = Color.Transparent;
_username.BorderStyle = 0;
_username.Visible = false;
But all this has achieved is allow me to set _username.BackColor = Color.Transparent; Without throwing an error. The Input box remains White with no border. I just want to make the background transparent. Even MSDN recomends this solution but It does not work for me. My only solution left is to build a custom Label class that grabs the inputs and reads the key inputs and adds them to the .Text property but I don't want to do this.
The solution in your linked answer works fine. If you're not using the designer it doesn't matter... you can still use the same solution. InitializeComponent() is simply a method that's created by the code generator in the designer file. If you ever want to know what it does to create controls (it can be very informational to have a look) then create a control using the designer and then inspect the .Designer.cs file.
EDIT: It acts a little funny. You can override OnPaint to fix the white background and disappearing text, see below. Not a "finished" implementation, the cursor doesn't seem to know where to go, but this should get you in the right direction.
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
for (int i = 0; i < 3; i++)
{
var x = new UserControl1 {Location = new Point(0, i*20)};
this.Controls.Add(x);
}
}
}
public class UserControl1 : TextBox
{
public UserControl1()
{
SetStyle(ControlStyles.SupportsTransparentBackColor |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.ResizeRedraw |
ControlStyles.UserPaint, true);
BackColor = Color.Transparent;
TextChanged += UserControl2_OnTextChanged;
}
protected override void OnPaint(PaintEventArgs e)
{
var backgroundBrush = new SolidBrush(Color.Transparent);
Graphics g = e.Graphics;
g.FillRectangle(backgroundBrush, 0, 0, this.Width, this.Height);
g.DrawString(Text, Font, new SolidBrush(ForeColor), new PointF(0,0), StringFormat.GenericDefault);
}
public void UserControl2_OnTextChanged(object sender, EventArgs e)
{
Invalidate();
}
}
}
When we use SetStyle(ControlStyles.UserPaint,true) Control Border Doesn't paint. I did this in Textbox. My textbox border style is FixedSingle but after using setstyle with UserPaint Textbox border is not drawn. Textbox appears like border is set to None.
I have a simple form as an example. I've added some check boxes using designer, and set the margin and padding to 0,0,0,0. This is the form code:
public partial class Frm1 : Form
{
public Frm1()
{
InitializeComponent();
AddCheckBox();
AddCheckBox();
AddCheckBox();
}
public void AddCheckBox()
{
CheckBox cb = new CheckBox();
cb.Text = "AddedFromCode";
cb.Padding = new Padding(0,0,0,0);
cb.Margin = new Padding(0,0,0,0);
flowLayoutPanel1.Controls.Add(cb);
}
}
I would expect the check boxes that are added from designer and from code to appear the same, however, they do not.
How can I get the spacing of the AddedFromCode controls to have 0 spacing?
I don't know why it took me so long to figure this out. One of the properties that designer changes when you add a control to a FlowLayoutPanel is AutoSize = true.
So in code...
cb.AutoSize= true;
solves the problem.
I need to have a MaskedTextBox in a ToolStrip, which isn't included by default, so I followed some advice I found online, and created custom control that inherits from ToolStripControlHost. What I've created works great when I'm running the application, but it really messes up the designer. By "messes up", I mean the custom control (Along with some others) disappear from the ToolStrip. Also I can no longer add new controls to the ToolStrip, and I can't select the existing controls on the ToolStrip to edit them.
Here's my class.
[DesignerCategory("code")]
[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ToolStrip | ToolStripItemDesignerAvailability.StatusStrip)]
public partial class ToolStripMaskedTextBox : ToolStripControlHost
{
public MaskedTextBox MaskedTextBox
{
get { return Control as MaskedTextBox; }
}
public ToolStripMaskedTextBox()
: base(CreateControlInstance()) { }
private static Control CreateControlInstance()
{
MaskedTextBox mtb = new MaskedTextBox();
mtb.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
mtb.MinimumSize = new System.Drawing.Size(100, 16);
mtb.PasswordChar = '*';
return mtb;
}
}
Any help on what I might be doing wrong that's giving the designer a hard time would be appreciated.
Addition Info
Now when I open my class file in Visual Studio, I get a warning page with the following error:
Constructor on type 'System.Windows.Forms.ToolStripControlHost' not found.
Addition Info 2
The problem only occurs after building the solution. I can get the designer working correctly by modifying the Form.Designer.cs file in even the smallest way. Like adding a single space. From there on out the designer will work fine. That is until I build the solution. Then the designer freezes up again. None of the controls on the form can be edited.
According to the exception
Constructor on type 'System.Windows.Forms.ToolStripControlHost' not found.
I found some information on the MSDN Forum.
This happends because the ToolStripControlHost class does not have a constructor with no parameter.
To solve this problem, you can create your own ToolStripControlHost with a none-parameter constructor and make the ToolStripMaskedTextBox inherited from your ToolStripControlHost. Try something like the following
//Declare a class that inherits from ToolStripControlHost.
[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ToolStrip | ToolStripItemDesignerAvailability.StatusStrip)]
public class ToolStripMaskedTextBox : MyCustomToolStripControlHost
{
// Call the base constructor passing in a MaskedTextBox instance.
public ToolStripMaskedTextBox() : base(CreateControlInstance()) { }
public MaskedTextBox MaskedTextBox
{
get
{
return Control as MaskedTextBox;
}
}
private static Control CreateControlInstance()
{
MaskedTextBox mtb = new MaskedTextBox();
mtb.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
mtb.MinimumSize = new System.Drawing.Size(100, 16);
mtb.PasswordChar = '*';
return mtb;
}
}
public class MyCustomToolStripControlHost : ToolStripControlHost
{
public MyCustomToolStripControlHost()
: base(new Control())
{
}
public MyCustomToolStripControlHost(Control c)
: base(c)
{
}
}
This will fix the problem with your exception.
The Problem with the Forms Designer (ToolStripMaskedTextBox is not visible after running the app) is not solved but you can close the designer and open the file again.
Then you can go on without any problems.
Hope this helps
I've used dknaack's solution, but placed MyCustomToolStripControlHost class in a separate file in System.Windows.Forms namespace. And...
First: it works - no exception.
Then: my control is visible in designer as well, so it's a jackpot.
In this link, the answer was that the objects that implement "blah" interface must have a parameter-less constructor. Give it a try.
FWIW: I also succeeded with dknaack's solution above, but only after I realized I was looking for the custom ToolStrip Control in the wrong place. The custom control doesn't show up in the Toolbox itself. Rather it shows up in the dropdown list of components under the "Add ToolStripButton" that appears on the ToolStrip when it is selected (in the designer).
I found a solution of designer's problem.
https://dobon.net/vb/dotnet/control/tschdesigneravail.html#tips_comment (Japanese)
All you need is just make a class derived from ToolStrip and substitute it.
class DesignerFriendlyToolStrip : ToolStrip { }
var ts = new DesignerFriendlyToolStrip();
ts.Items.Add(toolStripMaskedTextBox);
form.Controls.Add(ts);
I don't know why this is effective. Anyone knows...?
I have a winform application which has a dynamic number (based on a database value) of PictureBoxes. Each P-Box has a Tooltip control.
How can I change the ToolTip Text without having any memory leaks? Right now, I've got the following code, but it's leaking memory => the previous ToolTip controls are not getting GC'd.
BTW, this is a background thread that is trying to update the main UI thread....
if (pictureBox == null || !pictureBox.IsHandleCreated) {
continue;
}
Action setTooltipAndImage = () => {
var toolTip = new ToolTip();
GameServer tempGameFile = gameServer;
toolTip.SetToolTip(pictureBox, string.Format(...));
pictureBox.Image = Resources.RedButton;
};
if (pictureBox.InvokeRequired) {
pictureBox.Invoke(setTooltipAndImage);
} else {
setTooltipAndImage();
}
As I said - this works but it's leaking.
Anyone have any suggestions?
Don't create a new ToolTip each time. Add a ToolTip to the form using the visual designer, like you would for any other control or component. Call toolTip.SetToolTip(...) on the form's tool tip each time. The ToolTip will be disposed when the Form is disposed.
Yes, you do not need to create a new ToolTip each time, a single ToolTipwill do. There is no issue if you do not know how many ToolTips you want, because if there is only one ToolTip say toolTip1, then you can use the following every time you want to change the ToolTip caption and control on some event. You only need one ToolTip instance per form.
toolTip1.SetToolTip(Current_pictureBox, "<tool tip string>");
You only need one ToolTip instance per form.
toolTip.SetToolTip(control, caption) - can use with many control, you can set caption for each control
toolTip.ToolTipTitle - set tool tip title, the title is one for all control bonded with tool tip
for example :
public Form1()
{
InitializeComponent();
toolTip1.SetToolTip(button1, "btn1");
toolTip1.SetToolTip(button2, "btn2");
toolTip1.SetToolTip(button3, "btn3");
}
private void button4_Click(object sender, EventArgs e)
{
toolTip1.ToolTipTitle = textBox1.Text;
}