I have a Custom panel which contains 4 labels (in example pasted, I have erased definition of those 2 I didn't used).
This custom panel is added to a panel dynamically, as many records I have in an array.
The parent panel, has the Horizontal scroll enabled = false, as I should scroll only vertically.
Everything works fine, as I can use mouse on vertical scrollbar and I can scroll the panel container. But when I want to use mouse wheel to scroll all the custom panels (child objects) it does not do anything.
I have tried many of the solutions that works for other on this site, but none of them works for me and I don't know why.
I read about the panel has to have focus to be able to scroll, and I will have to pass the OnMouseWheel event to parent, in child. But I am not able to do it, I don't know how to do it.
my custom panel (child):
public class PlaylistRecords : Panel
{
public Label lblRecordNumber { get; private set; }
private Label lblRecordName;
public static int RecordNumber { get; set; }
public static String RecordName { get; set; }
public PlaylistRecords(
int RecordNumber,
String RecordName
)
{
InitializeComponent();
this.Size = new System.Drawing.Size(800,50);
this.BackColor = System.Drawing.Color.FromArgb(20,20,20);
PlaylistRecords.RecordNumber = RecordNumber;
PlaylistRecords.RecordName = RecordName;
this.lblRecordNumber.Text = PlaylistRecords.RecordNumber.ToString()+".";
this.lblRecordName.Text = PlaylistRecords.RecordName;
this.lblRecordNumber.Location = new System.Drawing.Point(2, (int)(this.Height - this.lblRecordNumber.Height) / 2);
this.lblRecordName.Location = new System.Drawing.Point(
this.lblRecordNumber.Location.X+ this.lblRecordNumber.Width+2,
(int)(this.Height - this.lblRecordName.Height) / 2);
}
private void InitializeComponent()
{
this.lblRecordNumber = new myLabel();
this.lblRecordName = new myLabel();
this.lblRegistPath = new myLabel();
this.SuspendLayout();
//
// lblRecordNumber
//
this.lblRecordNumber.Name = "lblRecordNumber";
this.lblRecordNumber.Size = new System.Drawing.Size(50, 23);
//
// lblRecordName
//
this.lblRecordName.Name = "lblRecordName";
this.lblRecordName.Size = new System.Drawing.Size(150, 23);
//
// PlaylistRecords
//
this.Controls.Add(this.lblRecordNumber);
this.Controls.Add(this.lblRecordName);
this.ResumeLayout(false);
}
}
this.SetStyle(ControlStyles.Selectable, true);
this.TabStop = true;
These two lines of code written in constructor of child control (panel) is doing the job.
Thank you #Hans Passant for your comment. :)
Well if a control is not accepting events then they would be passed to parent
lblRecordNumber.Enabled = false;
lblRecordName.Enabled = false;
alternatively you can pass the scroll event to containing control referred to as Parent
internal class myLabel : Label
{
const int WM_MOUSEWHEEL = 0x020A;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_MOUSEWHEEL)
m.HWnd = this.Parent.Handle;
base.WndProc(ref m);
}
}
and use that control instead.
I have an integer array declared in a class. Using that array, a PolyLine is drawn on a grid. The elements of the array are the y-coordinates. The array has to updated continuously and then the values are to be displayed. My idea of implementing this is to have two threads. One to update the values of the array and the other to print PolyLine on the grid.
Updating the array is not a problem. When I try to print PolyLine on the grid using the code below, an exception is thrown with the following message: "The calling thread cannot access this object because a different thread owns it."
Kindly suggest a workaround for this problem using thread. Perhaps, an event may be used instead of thread? I am open to suggestions. Any help is appreciated!
public partial class MainWindow : Window
{
Polyline Wave = new Polyline();
public MainWindow()
{
InitializeComponent();
Refresh();
DisplyOnGrid();
ThreadStart child = new ThreadStart(DisplyOnGrid);
Thread _DisplayOnGrid = new Thread(child);
_DisplayOnGrid.Priority = ThreadPriority.Highest;
_DisplayOnGrid.Start();
}
private void DisplyOnGrid()
{
Wave.Stroke = Brushes.Yellow;
Wave.StrokeThickness = 1.25;
for (int i = 0; i < DisplayGrid.Width; i++)
{
Wave.Points.Add(new Point(i, 50));
}
DisplayGrid.Children.Add(Wave);
}
private void Refresh()
{
DisplayGrid.Children.Clear();
}
}
You are getting Error because you are trying to access object which is owned by UI/Dispatcher thread
try something like this:
private void DisplyOnGrid()
{
Dispatcher.Invoke(new Action(()=>
{
Wave.Stroke = Brushes.Yellow;
Wave.StrokeThickness = 1.25;
for (int i = 0; i < DisplayGrid.Width; i++)
{
Wave.Points.Add(new Point(i, 50));
}
DisplayGrid.Children.Add(Wave);
}
))};
I am working in Xamarin.iOS and I have UIToolbar that needs to be able to add and remove buttons from it programmatically at run-time.
I have tried several different approaches using: _buttons is a UIBarButtonItem[]
SetItems(_buttons, false)
and the toolbar never seems to update.
I initialize the toolbar when the app starts up with its main three buttons. When certain things happen, I need to be able to remove buttons from the toolbar as well as add new items to the toolbar.
I have also tried calling:
SetNeedsDisplay()
after calling:
SetItems(_buttons, false)
and this doesn't update the toolbar items either.
Any suggestions?
And the reason it is not changing because LayoutSubviews is called all the time and overrides your SetItems. Use constructor to populate toolbar first time
public partial class CustomUiToolbar : UIToolbar
{
public CustomUiToolbar (IntPtr handle) : base (handle)
{
var _UIBarButtonItemArrayOne = new UIBarButtonItem[3];
for (int i = 0; i < 3; i++)
{
var _item = new UIBarButtonItem(i.ToString(), UIBarButtonItemStyle.Done, null);
_item.TintColor = UIColor.Red;
_UIBarButtonItemArrayOne[i] = _item;
}
//var __UIBarButtonItemArrayTwo = new UIBarButtonItem[2];
//for (int i = 0; i < 2; i++)
//{
// var _item = new UIBarButtonItem(i.ToString(), UIBarButtonItemStyle.Done, null);
// _item.TintColor = UIColor.Blue;
// __UIBarButtonItemArrayTwo[i] = _item;
//}
SetItems(_UIBarButtonItemArrayOne, true);
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
}
}
Picture the notification-dropdown menu from Facebook.
I want to implement something similar. When clicking 'Slet', it's supposed to delete that notification from the list.
private void AddNotificationsToPanel(List<Notification> notifications, StackPanel panel)
{
panel.Children.Clear();
foreach (var notification in notifications)
{
//We want every message to have text, a delete button and a postpone button
//So we need a nested stackpanel:
var horizontalStackPanel = new StackPanel();
horizontalStackPanel.Orientation = Orientation.Horizontal;
panel.Children.Add(horizontalStackPanel);
//Display the message:
var text = new TextBlock();
text.Text = notification.Message;
text.Foreground = Brushes.Black;
text.Background = Brushes.White;
text.FontSize = 24;
horizontalStackPanel.Children.Add(text);
//Add a delete button:
var del = new Button();
del.Content = "Slet";
del.FontSize = 24;
del.Command = DeleteNotificationCommand;
horizontalStackPanel.Children.Add(del);
//Add a postpone button:
var postpone = new Button();
postpone.Content = "Udskyd";
postpone.FontSize = 24;
postpone.IsEnabled = false;
horizontalStackPanel.Children.Add(postpone);
}
panel.Children.Add(new Button { Content = "Luk", FontSize = 24, Command = ClosePopupCommand });
}
Basically, I have a vertical stackpanel with x amount of horizontal stackpanels. Each of those have a textbox and two buttons.
How do I know which button I clicked? The buttons are all bound to a delete command, but I'm kind of unsure how these work:
public ICommand DeleteNotificationCommand
{
get{
return new RelayCommand(o => DeleteNotification());
}
}
Which then create this method:
private void DeleteNotification()
{
Notifications.Remove(NotificationForDeletion);
AddNotificationsToPanel(Notifications, Panel);
}
Problem is we don't know which Notification to delete, because I don't know how to see which button was clicked. Any ideas?
You should use CommandParameter property of the button by assigning unique identifier of each notification to it. I'm assuming your notification has an unique integer id:
//Add a delete button:
var del = new Button();
del.Content = "Slet";
del.FontSize = 24;
del.Command = DeleteNotificationCommand;
del.CommandParameter = notification.Id; // <-- unique id
horizontalStackPanel.Children.Add(del);
Then in the DeleteNotification method, you need to specify a parameter for the key.
public ICommand DeleteNotificationCommand
{
get{
return new RelayCommand(DeleteNotification);
}
}
private void DeleteNotification(object parameter)
{
int notificationId = (int)parameter;
var NotificationForDeletion = ...; // <--- Get notification by id
Notifications.Remove(NotificationForDeletion);
AddNotificationsToPanel(Notifications, Panel);
}
Now, in the DeleteNotification you can identify the Notification that is related to the button.
This question already has answers here:
Hiding and Showing TabPages in tabControl
(21 answers)
Closed 7 years ago.
How to hide TabPage from TabControl in WinForms 2.0?
No, this doesn't exist. You have to remove the tab and re-add it when you want it. Or use a different (3rd-party) tab control.
Code Snippet for Hiding a TabPage
private void HideTab1_Click(object sender, EventArgs e)
{
tabControl1.TabPages.Remove(tabPage1);
}
Code Snippet for Showing a TabPage
private void ShowTab1_Click(object sender, EventArgs e)
{
tabControl1.TabPages.Add(tabPage1);
}
I realize the question is old, and the accepted answer is old, but ...
At least in .NET 4.0 ...
To hide a tab:
tabControl.TabPages.Remove(tabPage);
To put it back:
tabControl.TabPages.Insert(index, tabPage);
TabPages works so much better than Controls for this.
Visiblity property has not been implemented on the Tabpages, and there is no Insert method also.
You need to manually insert and remove tab pages.
Here is a work around for the same.
http://www.dotnetspider.com/resources/18344-Hiding-Showing-Tabpages-Tabcontrol.aspx
Variant 1
In order to avoid visual klikering you might need to use:
bindingSource.RaiseListChangeEvent = false
or
myTabControl.RaiseSelectedIndexChanged = false
Remove a tab page:
myTabControl.Remove(myTabPage);
Add a tab page:
myTabControl.Add(myTabPage);
Insert a tab page at specific location:
myTabControl.Insert(2, myTabPage);
Do not forget to revers the changes:
bindingSource.RaiseListChangeEvent = true;
or
myTabControl.RaiseSelectedIndexChanged = true;
Variant 2
myTabPage.parent = null;
myTabPage.parent = myTabControl;
Solutions provided so far are way too complicated.
Read the easiest solution at:
http://www.codeproject.com/Questions/614157/How-to-Hide-TabControl-Headers
You could use this method to make them invisible at run time:
private void HideAllTabsOnTabControl(TabControl theTabControl)
{
theTabControl.Appearance = TabAppearance.FlatButtons;
theTabControl.ItemSize = new Size(0, 1);
theTabControl.SizeMode = TabSizeMode.Fixed;
}
I combined the answer from #Jack Griffin and the one from #amazedsaint (the dotnetspider code snippet respectively) into a single TabControlHelper.
The TabControlHelper lets you:
Show / Hide all tab pages
Show / Hide single tab pages
Keep the original position of the tab pages
Swap tab pages
public class TabControlHelper
{
private TabControl _tabControl;
private List<KeyValuePair<TabPage, int>> _pagesIndexed;
public TabControlHelper(TabControl tabControl)
{
_tabControl = tabControl;
_pagesIndexed = new List<KeyValuePair<TabPage, int>>();
for (int i = 0; i < tabControl.TabPages.Count; i++)
{
_pagesIndexed.Add(new KeyValuePair<TabPage, int> (tabControl.TabPages[i], i ));
}
}
public void HideAllPages()
{
for (int i = 0; i < _pagesIndexed.Count; i++)
{
_tabControl.TabPages.Remove(_pagesIndexed[i].Key);
}
}
public void ShowAllPages()
{
for (int i = 0; i < _pagesIndexed.Count; i++)
{
_tabControl.TabPages.Add(_pagesIndexed[i].Key);
}
}
public void HidePage(TabPage tabpage)
{
if (!_tabControl.TabPages.Contains(tabpage)) return;
_tabControl.TabPages.Remove(tabpage);
}
public void ShowPage(TabPage tabpage)
{
if (_tabControl.TabPages.Contains(tabpage)) return;
InsertTabPage(GetTabPage(tabpage).Key, GetTabPage(tabpage).Value);
}
private void InsertTabPage(TabPage tabpage, int index)
{
if (index < 0 || index > _tabControl.TabCount)
throw new ArgumentException("Index out of Range.");
_tabControl.TabPages.Add(tabpage);
if (index < _tabControl.TabCount - 1)
do
{
SwapTabPages(tabpage, (_tabControl.TabPages[_tabControl.TabPages.IndexOf(tabpage) - 1]));
}
while (_tabControl.TabPages.IndexOf(tabpage) != index);
_tabControl.SelectedTab = tabpage;
}
private void SwapTabPages(TabPage tabpage1, TabPage tabpage2)
{
if (_tabControl.TabPages.Contains(tabpage1) == false || _tabControl.TabPages.Contains(tabpage2) == false)
throw new ArgumentException("TabPages must be in the TabControls TabPageCollection.");
int Index1 = _tabControl.TabPages.IndexOf(tabpage1);
int Index2 = _tabControl.TabPages.IndexOf(tabpage2);
_tabControl.TabPages[Index1] = tabpage2;
_tabControl.TabPages[Index2] = tabpage1;
}
private KeyValuePair<TabPage, int> GetTabPage(TabPage tabpage)
{
return _pagesIndexed.Where(p => p.Key == tabpage).First();
}
}
Example on how to use it:
TabControl myTabControl = new TabControl();
TabControlHelper myHelper = new TabControlHelper(myTabControl);
myHelper.HideAllPages();
myHelper.ShowAllPages();
private System.Windows.Forms.TabControl _tabControl;
private System.Windows.Forms.TabPage _tabPage1;
private System.Windows.Forms.TabPage _tabPage2;
...
// Initialise the controls
...
// "hides" tab page 2
_tabControl.TabPages.Remove(_tabPage2);
// "shows" tab page 2
// if the tab control does not contain tabpage2
if (! _tabControl.TabPages.Contains(_tabPage2))
{
_tabControl.TabPages.Add(_tabPage2);
}
Create a new empty class and past this inside it:
using System.Windows.Forms;
namespace ExtensionMethods
{
public static class TabPageExtensions
{
public static bool IsVisible(this TabPage tabPage)
{
if (tabPage.Parent == null)
return false;
else if (tabPage.Parent.Contains(tabPage))
return true;
else
return false;
}
public static void HidePage(this TabPage tabPage)
{
TabControl parent = (TabControl)tabPage.Parent;
parent.TabPages.Remove(tabPage);
}
public static void ShowPageInTabControl(this TabPage tabPage,TabControl parent)
{
parent.TabPages.Add(tabPage);
}
}
}
2- Add reference to ExtensionMethods namespace in your form code:
using ExtensionMethods;
3- Now you can use yourTabPage.IsVisible(); to check its visibility, yourTabPage.HidePage(); to hide it, and yourTabPage.ShowPageInTabControl(parentTabControl); to show it.
you can set the parent of the tabpage to null for hiding
and to show just set tabpage parent to the tabcontrol
public static Action<Func<TabPage, bool>> GetTabHider(this TabControl container) {
if (container == null) throw new ArgumentNullException("container");
var orderedCache = new List<TabPage>();
var orderedEnumerator = container.TabPages.GetEnumerator();
while (orderedEnumerator.MoveNext()) {
var current = orderedEnumerator.Current as TabPage;
if (current != null) {
orderedCache.Add(current);
}
}
return (Func<TabPage, bool> where) => {
if (where == null) throw new ArgumentNullException("where");
container.TabPages.Clear();
foreach (TabPage page in orderedCache) {
if (where(page)) {
container.TabPages.Add(page);
}
}
};
}
Use it like this:
var hider = this.TabContainer1.GetTabHider();
hider((tab) => tab.Text != "tabPage1");
hider((tab) => tab.Text != "tabpage2");
The original ordering of the tabs is kept in a List that is completely hidden inside the anonymous function. Keep a reference to the function instance and you retain your original tab order.
Well, if you don't want to mess up existing code and just want to hide a tab, you could modify the compiler generated code to comment the line which adds the tab to the tabcontrol.
For example:
The following line adds a tab named "readformatcardpage" to a Tabcontrol named "tabcontrol"
this.tabcontrol.Controls.Add(this.readformatcardpage);
The following will prevent addition of the tab to the tabcontrol
//this.tabcontrol.Controls.Add(this.readformatcardpage);
+1 for microsoft :-) .
I managed to do it this way:
(it assumes you have a Next button that displays the next TabPage - tabSteps is the name of the Tab control)
At start up, save all the tabpages in a proper list.
When user presses Next button, remove all the TabPages in the tab control, then add that with the proper index:
int step = -1;
List<TabPage> savedTabPages;
private void FMain_Load(object sender, EventArgs e) {
// save all tabpages in the list
savedTabPages = new List<TabPage>();
foreach (TabPage tp in tabSteps.TabPages) {
savedTabPages.Add(tp);
}
SelectNextStep();
}
private void SelectNextStep() {
step++;
// remove all tabs
for (int i = tabSteps.TabPages.Count - 1; i >= 0 ; i--) {
tabSteps.TabPages.Remove(tabSteps.TabPages[i]);
}
// add required tab
tabSteps.TabPages.Add(savedTabPages[step]);
}
private void btnNext_Click(object sender, EventArgs e) {
SelectNextStep();
}
Update
public class TabControlHelper {
private TabControl tc;
private List<TabPage> pages;
public TabControlHelper(TabControl tabControl) {
tc = tabControl;
pages = new List<TabPage>();
foreach (TabPage p in tc.TabPages) {
pages.Add(p);
}
}
public void HideAllPages() {
foreach(TabPage p in pages) {
tc.TabPages.Remove(p);
}
}
public void ShowAllPages() {
foreach (TabPage p in pages) {
tc.TabPages.Add(p);
}
}
public void HidePage(TabPage tp) {
tc.TabPages.Remove(tp);
}
public void ShowPage(TabPage tp) {
tc.TabPages.Add(tp);
}
}
TabPage pageListe, pageDetay;
bool isDetay = false;
private void btnListeDetay_Click(object sender, EventArgs e)
{
if (isDetay)
{
isDetay = false;
tc.TabPages.Remove(tpKayit);
tc.TabPages.Insert(0,pageListe);
}
else
{
tc.TabPages.Remove(tpListe);
tc.TabPages.Insert(0,pageDetay);
isDetay = true;
}
}
As a cheap work around, I've used a label to cover up the tabs I wanted to hide.
We can then use the visible prop of the label as a substitute. If anyone does go this route, don't forget to handle keyboard strokes or visibility events. You wouldn't want the left right cursor keys exposing the tab you're trying to hide.
Not sure about "Winforms 2.0" but this is tried and proven:
http://www.mostthingsweb.com/2011/01/hiding-tab-headers-on-a-tabcontrol-in-c/
In WPF, it's pretty easy:
Assuming you've given the TabItem a name, e.g.,
<TabItem Header="Admin" Name="adminTab" Visibility="Hidden">
<!-- tab content -->
</TabItem>
You could have the following in the code behind the form:
if (user.AccessLevel == AccessLevelEnum.Admin)
{
adminTab.Visibility = System.Windows.Visibility.Visible;
}
It should be noted that a User object named user has been created with it's AccessLevel property set to one of the user-defined enum values of AccessLevelEnum... whatever; it's just a condition by which I decide to show the tab or not.
I also had this question. tabPage.Visible is not implemented as stated earlier, which was a great help (+1). I found you can override the control and this will work. A bit of necroposting, but I thought to post my solution here for others...
[System.ComponentModel.DesignerCategory("Code")]
public class MyTabPage : TabPage
{
private TabControl _parent;
private bool _isVisible;
private int _index;
public new bool Visible
{
get { return _isVisible; }
set
{
if (_parent == null) _parent = this.Parent as TabControl;
if (_parent == null) return;
if (_index < 0) _index = _parent.TabPages.IndexOf(this);
if (value && !_parent.TabPages.Contains(this))
{
if (_index > 0) _parent.TabPages.Insert(_index, this);
else _parent.TabPages.Add(this);
}
else if (!value && _parent.TabPages.Contains(this)) _parent.TabPages.Remove(this);
_isVisible = value;
base.Visible = value;
}
}
protected override void InitLayout()
{
base.InitLayout();
_parent = Parent as TabControl;
}
}
I've used the same approach but the problem is that when tab page was removed from the tab control TabPages list, it is removed from the tab page Controls list also. And it is not disposed when form is disposed.
So if you have a lot of such "hidden" tab pages, you can get windows handle quota exceeded error and only application restart will fix it.
If you are talking about AjaxTabControlExtender then set TabIndex of every tabs and set Visible property True/False according to your need.
myTab.Tabs[1].Visible=true/false;
// inVisible
TabPage page2 = tabControl1.TabPages[0];
page2.Visible= false;
//Visible
page2.Visible= true;
// disable
TabPage page2 = tabControl1.TabPages[0];
page2.Enabled = false;
// enable
page2.Enabled = true;
//Hide
tabCtrlTagInfo.TabPages(0).Hide()
tabCtrlTagInfo.TabPages(0).Show()
Just copy paste and try it,the above code has been tested in vs2010, it works.
Hide TabPage and Remove the Header:
this.tabPage1.Hide();
this.tabPage3.Hide();
this.tabPage5.Hide();
tabControl1.TabPages.Remove(tabPage1);
tabControl1.TabPages.Remove(tabPage3);
tabControl1.TabPages.Remove(tabPage5);
Show TabPage and Visible the Header:
tabControl1.TabPages.Insert(0,tabPage1);
tabControl1.TabPages.Insert(2, tabPage3);
tabControl1.TabPages.Insert(4, tabPage5);
this.tabPage1.Show();
this.tabPage3.Show();
this.tabPage5.Show();
tabControl1.SelectedTab = tabPage1;