I have a LayoutAnchorablePane and some LayoutAnchorable's inside the pane. When I float the LayoutAnchorablePane and try to close it, it just tries to close every children inside the LayoutAnchorablePane (closing event being fired more than one time but I only want to close the intented LayoutAnchorable)
How can I solve this strange issue?
Here is the code I'm dealing with
_layoutAnchorable.Closing += (senderObj, args) =>
{
LayoutAnchorable layoutAnchorable = senderObj as LayoutAnchorable;
string module = App.XmlDataProviderInstance.GetActiveModuleName().Result;
MessageBoxResult result = MessageBox.Show("Are you sure you want to exit?\n\nThere might be unsaved changes.",
"Unsaved Changes", MessageBoxButton.YesNoCancel, MessageBoxImage.Information);
if (result == MessageBoxResult.No)
{
args.Cancel = true;
return;
}
else if (result == MessageBoxResult.Yes)
{
if (LayoutUndoMap.ElementLayoutUndoMap[layoutAnchorable.GetHashCode()] > 0)
{
for (int i = 0; i < LayoutUndoMap.ElementLayoutUndoMap[layoutAnchorable.GetHashCode()]; i++)
{
App.XmlDataProviderInstance.Undo();
}
}
var closingLayoutAnchorable = (LayoutAnchorable)senderObj;
if (elementLayoutAnchorableContentIds.Contains(closingLayoutAnchorable.ContentId))
{
elementLayoutAnchorableContentIds.Remove(closingLayoutAnchorable.ContentId);
}
((ListBoxItem)_elementListBox.ItemContainerGenerator.ContainerFromIndex(0)).Background = Brushes.White; // index needs to be set correctly!
App.XmlDataProviderInstance.SetActiveModule(module);
return;
}
args.Cancel = true;
};
this event is working perfectly fine when I don't float the windows. But when I do, it closes every children.
Related
I am facing issue in tabcontrol of Windows application.
We have a tabcontrol on 1 windows form on which first tab is by default and other tabs we are adding dynamically at runtime.
In first case while we opening the form, we able to see all the controls in both the tabs i.e. (Default and other tabs)
Although, when we try opening the form for second time, data is being getting added into the form if we debug but while showing, it shows blank in other tabs which are getting added dynamically.
In CustomgroupControl class, i am adding controls dynamically like textbox, dropdown, grid and etc. Although this is working in first case, but not showing controls in second case. (Flow of code is same for both the cases)
Below is attached screenshot in link and shown sample source code
Screenshot for above query
public void renderTabpage(Dictionary<string, List<Field>> subHeaderMap, TabPage currentTabPage, AsynchTabRenderer asynchTabRenderer, DoWorkEventArgs e)
{
currentTabPage.SuspendLayout();
TableLayoutPanel headerTableLayout = createNewheaferTableLayoutPanel(currentTabPage.Name + TABLE_LAYOUT_NAME_SUFFIX);
currentTabPage.Controls.Add(headerTableLayout);
headerTableLayout.ColumnCount = 1;
headerTableLayout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
headerTableLayout.RowCount = 0;
headerTableLayout.SuspendLayout();
foreach (string subHeaderName in subHeaderMap.Keys)
{
if (asynchTabRenderer != null && asynchTabRenderer.CancellationPending == true)
{
e.Cancel = true;
return;
}
else
{
CustomGroupControl customGroupControl = createAndPopulateSubheaderGroupControl(subHeaderMap[subHeaderName], subHeaderName);
headerTableLayout.RowCount = headerTableLayout.RowCount + 1;
headerTableLayout.RowStyles.Add(new RowStyle(SizeType.AutoSize));
headerTableLayout.Controls.Add(customGroupControl, 0, ++headerTableLayout.RowCount);
}
}
headerTableLayout.ResumeLayout(false);
headerTableLayout.PerformLayout();
currentTabPage.ResumeLayout(false);
currentTabPage.PerformLayout();
}
private void detailsTabControl_TabIndexChanged(object sender, EventArgs e)
{
tabIndexChangedEvent(((TabControl)sender).SelectedTab);
}
private void tabIndexChangedEvent(TabPage tabPage)
{
try
{
//WordApp.ScreenUpdating = false;
//WordApp.System.Cursor = Word.WdCursorType.wdCursorWait;
if (tabPage.Name == TabName.Replace(" ", "_").ToUpper())
{
FileUtilService service = FileUtilFactory.getInstance();
// service.clearIENetCache();
showForm(Window, forms);
}
//TabPage tabPage = ((TabControl)sender).SelectedTab;
if ((tabPage.Tag == null || true == (Boolean)tabPage.Tag) && !string.Equals(tabPage.Name, FieldConstants.TAB, StringComparison.CurrentCultureIgnoreCase))
{
var controls = WindowsFormControlUtils.GetControlHierarchy(tabPage);
foreach (Control control in controls)
{
if (control is CustomGroupControl)
{
CustomGroupControl customGroupControl = (CustomGroupControl)control;
customGroupControl.fieldRenderDelegater();
}
else
continue;
}
tabPage.Tag = false;
}
}
catch (Exception ex)
{
logger.Error(ex.Message);
}
}
internal TableLayoutPanel createNewheaferTableLayoutPanel(string headerName)
{
TableLayoutPanel subHeaderTableLayout = new TableLayoutPanel();
// resources.ApplyResources(subHeaderTableLayout, headerName.Replace(" ", "_").ToUpper());
subHeaderTableLayout.Name = headerName.Replace(" ", "_").ToUpper() + TABLE_LAYOUT_NAME_SUFFIX;
subHeaderTableLayout.Dock = DockStyle.Fill;
subHeaderTableLayout.AutoSize = true;
subHeaderTableLayout.AutoScroll = true;
subHeaderTableLayout.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowOnly;
subHeaderTableLayout.GrowStyle = TableLayoutPanelGrowStyle.AddRows;
return subHeaderTableLayout;
}
#Jimi & #Lucky
It works. Got the correct direction. Thanks.
Hint - Don't create controls on worker thread
Tried solution and worked - Removed creation of controls from parameterized constructor and added on form_load event.
I have a handler for Closing event of a tab, it shows a confirm closing message.
if the user choose No, I set e.Handled = true; but if he chooses Yes close, I remove the tab from the tab list and do other stuff,
when the method reaches its end, it then get called again, showing the same message, I tried to set e.Handled = true; in the end of the method but the tab doesn't close.
void oTab_TabClosing(object sender, RoutedEventArgs e)
{
var close = MainClass.ShowMessage(ResCommon.MsgConfirmClose, ResCommon.ttlClose, MainClass.MessageButtons.YesNO);
if (!close)
{
e.Handled = true;
return;
}
FabTab.FabTabItem oTabItem = (FabTab.FabTabItem)sender;
if (HtOpenTabs.ContainsKey(oTabItem.Name)) HtOpenTabs.Remove(oTabItem.Name);
oTabItem = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}
This method subscribe to the event:
public void AddToTab(object formToOpen, string formTitle)
{
string formName = ((UserControl)formToOpen).Name;
if (HtOpenTabs.ContainsKey(formName))
{
// By Yousef Mohamed (12-10-2014) - Activate opened tab //
foreach (FabTabItem item in ((FabTabControl)this.tabControl).Items)
{
if (item.Name == formName)
{
((FabTabControl)this.tabControl).SelectedItem = item;
return;
}
}
}
var oTab = new FabTabItem { Content = formToOpen };
oTab.Name = formName;
oTab.TabClosing += oTab_TabClosing;
oTab.Header = formTitle;
BrushConverter bc = new BrushConverter();
Brush brush = (Brush)bc.ConvertFrom("#FFF0F8FF");
brush.Freeze();
oTab.Background = brush;
oTab.Height = 30;
tabControl.Items.Add(oTab);
tabControl.SelectedIndex = tabControl.Items.Count - 1;
HtOpenTabs.Add(formName, oTab);
}
It seems that second event is fired in the HtOpenTabs.Remove(oTabItem.Name);
Try to unsubscribe this event handler before removing your tab.
I'm making a memotest and I need to press two different images and they need to keep visible for 3-5 seconds. I've tried Thread.Sleep(5000) but it doesn't show me the second one. What should I do?
The only way I've founded to see for some seconds the images was by putting a MessageBox but that isn't the idea and I don't know other way to do it.
if (pic != null && pic.Name == fondos[i].Name)
{
if (CantClick == 0)
{
ParejaActual = listRandom[i].pareja;
CantClick = 1;
primerI = i;
picAnterior = pic;
imgAnterior = img;
pic.Visible = false;
}
else if (CantClick == 1)
{
pic.Visible = false;
if (ParejaActual == listRandom[i].pareja)
{
SoundPlayer simpleSound = (new SoundPlayer(Configuracion.RootFolder + "aplau.wav"));
simpleSound.Play();
Ganando++;
label3.Text = Ganando.ToString();
//MessageBox.Show("Si");
//NO SE DESTAPA LA SEGUNDA.
//Thread.Sleep(5000);
CantClick = 0;
img.Visible = false;
imgAnterior.Visible = false;
Application.DoEvents();
}
else
{
(new SoundPlayer(Configuracion.RootFolder + "sad.wav")).Play();
MessageBox.Show("No");
Mal++;
CantClick = 0;
label4.Text = Mal.ToString();
pic.Visible = true;
picAnterior.Visible = true;
}
}
}
Thank you!
Instead of using Thread.Sleep , use System.Timers class. After an interval, just hide one image and show the other. Tell me if you want any other help.
I have two controls on the same form. Both controls contain an ObjectListView control. The one listview was created with the graphical editor in visual studio. This one is not causing any issues. The other listview is created programmatically at run-time. I have defined an event handler for each control that gets called when the hot item changes and they are both firing when they should. Both event handlers call the same code to update a picturebox control. The problem is that the picturebox does not get updated when the programmatically defined listview is asking it to. I am positive the event handler is getting called because my code writes to a text file as well as updating the picture box. The text file gets updated but the picture box does not. I have tried updating, invalidating, and refreshing the PicutureBox as well as the parent form, but I just can not get it to update.
I am not sure if this is an ObjectListView issue or a standard WinForms problem. I realize my question is very vague but I am not sure how to clarify it without posting all my code. Any advice would be appreciated.
Here is the code that the event handler calls:
public void ShowBitmap(object sender, HotItemChangedEventArgs e, ObjectListView lv, string type)
{
ObjectListView olv = sender as ObjectListView;
if (sender == null)
{
return;
}
switch (e.HotCellHitLocation)
{
case HitTestLocation.Nothing:
break;
case HitTestLocation.Group:
break;
case HitTestLocation.GroupExpander:
break;
default:
if (e.HotColumnIndex == 0)
{
pictureBox1.Hide();
pictureBox1.BorderStyle = BorderStyle.FixedSingle;
int rowIndex = e.HotRowIndex;
string text = "";
if (type == "Main Parts")
{
TypedObjectListView<MainRadanProjectPartsPart> tlist = new TypedObjectListView<MainRadanProjectPartsPart>(lv);
text = tlist.Objects[rowIndex].Symbol;
}
else if (type == "Parts")
{
TypedObjectListView<RadanProjectPartsPart> tlist = new TypedObjectListView<RadanProjectPartsPart>(lv);
text = tlist.Objects[rowIndex].Symbol;
}
else if (type == "Nests")
{
TypedObjectListView<MainRadanProjectNestsNest> tlist = new TypedObjectListView<MainRadanProjectNestsNest>(lv);
text = tlist.Objects[rowIndex].FileName;
}
if (text != null)
{
Point screenCoords = Cursor.Position;
Point controlRelatedCoords = lv.PointToClient(screenCoords);
if (controlRelatedCoords.Y < oldCursorPosition.Y)
{
pictureBox1.Location = controlRelatedCoords;
int xPos = controlRelatedCoords.X;
int yPos = controlRelatedCoords.Y + 60;
pictureBox1.Location = new Point(xPos, yPos);
}
else if (controlRelatedCoords.Y > oldCursorPosition.Y)
{
pictureBox1.Location = controlRelatedCoords;
int xPos = controlRelatedCoords.X;
//int yPos = controlRelatedCoords.Y - pictureBox1.Height;
int yPos = controlRelatedCoords.Y - pictureBox1.Height + 30;
pictureBox1.Location = new Point(xPos, yPos);
}
pictureBox1.Show();
pictureBox1.BringToFront();
olvTreeViewMainParts.Focus();
lv.Focus();
pictureBox1.Visible = true;
DrawSymbol(text);
oldCursorPosition = controlRelatedCoords; // save the cursor position to track cursor direction between calls
}
else
{
DrawSymbol("");
}
}
else
{
pictureBox1.Hide();
}
break;
}
}
Here is the event handler for the programmaticaly defined listview:
// track the cursor as it moves over the items in the listview
private void olvPartsListView_HotItemChanged(object sender, HotItemChangedEventArgs e)
{
ShowBitmap(sender, e, olvPartsListView, "Parts");
}
I've a panel.
I add WinForms inside it. The WinForms added have the TopLevel and Visible properties set to FALSE and TRUE.
I can do a panel.SetChildIndex(WinForm1,0) to bring WinForm1 to front.
What I've not managed to do is keep a track of the actual ChildIndex of the panel.
The idea is to have buttons that opens forms inside the panel, and that when the panel opens a new button is added in a Windows menu.
Something like when many files are open on a VS Project, you can go to Window menu and select one. Also, if you change the active page by clicking the page, the Window menu auto-updates and checks the actual active page.
I want to do this, but with a panel container. I've managed to get done everithing, but not the the Window menu auto-updates and checks the actual active page part.
Isn't there an event fired when BringToFront() or SetChildIndex(form, index) are called? Any event when I click another form that's inside the panel and it becomes the "active one"? Or some property of the panel that I can keep track of that changes when active form changes?
It is taken from here
When Control's ZOrder is chaged layout operation is always performed
in control's container control.
When I subscribed to container's Layout event and called
BringToFront() it showed me Control that changed its
ZOrder(LayoutEventArgs.AffectedControl) and changed property
(LayoutEventArgs.AffectedProperty).
Found that when a form inside a panel is closed, the Controls property of the panel gets reindexed, where the index zero is the form that gets the new focus. Now that I've a way to check the form that's in front when I close another one, windows administration in panels is done.
Going to put the source code, maybe it can help someone :)
Please note that I'm using a RadRibbonForm, a standard panel, and RadForms inside the panel. Rad's are from Telerik. Some things should change to make this work on standardWinForms, but the changes are minimal.
Also, I'm not using a menu that shows the forms, I'm using RadButtonElement's in a page of the ribbon menu instead.
AddRadFormWindow must be called to put a window and manage it automatically.
Example of adding a window:
AddRadFormWindow(typeof (MyRadForm))
Now, the source. It must be inside the code of the RadRibbonForm's class.
public static class ExtensionsRadForm
{
[DllImport("user32.dll")]
private static extern int ShowWindow(IntPtr hWnd, uint msg);
public static void Deminimize(this RadForm form)
{
if (form.WindowState == FormWindowState.Minimized)
ShowWindow(form.Handle, 9);
}
}
private void RefreshButtonsChecks(string windowName)
{
if (windowName != null)
{
principalPanel.Controls[windowName].BringToFront();
}
if (principalPanel.Controls.Count > 0)
{
if (principalPanel.Controls.Cast<RadForm>().Any(radForm => radForm.WindowState != FormWindowState.Minimized))
{
foreach (RadItem item in radRibbonBarGroupOpenWindows.Items)
{
var buttonBorder = ((RadButtonElement) item).BorderElement;
if (item.Name == panelPrincipal.Controls[0].Name + "Button")
{
buttonBorder.ForeColor = Color.LimeGreen;
buttonBorder.BottomColor = Color.LimeGreen;
buttonBorder.TopColor = Color.LimeGreen;
buttonBorder.LeftColor = Color.LimeGreen;
buttonBorder.RightColor = Color.LimeGreen;
principalPanel.Controls[0].Focus();
}
else
{
buttonBorder.ForeColor = Color.Transparent;
buttonBorder.BottomColor = Color.Transparent;
buttonBorder.TopColor = Color.Transparent;
buttonBorder.LeftColor = Color.Transparent;
buttonBorder.RightColor = Color.Transparent;
}
}
}
else
{
foreach (RadItem item in radRibbonBarGroupAbiertas.Items)
{
var buttonBorder = ((RadButtonElement)item).BorderElement;
buttonBorder.ForeColor = Color.Transparent;
buttonBorder.BottomColor = Color.Transparent;
buttonBorder.TopColor = Color.Transparent;
buttonBorder.LeftColor = Color.Transparent;
buttonBorder.RightColor = Color.Transparent;
}
}
}
}
private void PrincipalPanelLayout(object sender, LayoutEventArgs e)
{
RefreshButtonsChecks(null);
}
private void RadButtonElementCloseAllWindowsClick(object sender, EventArgs e)
{
int limitButtons = radRibbonBarGroupOpenWindows.Items.Count;
for (int index = 0; index < limitButtons; index++)
{
RadItem radItem = radRibbonBarGroupOpenWindows.Items[0];
radItem.Dispose();
}
int limitControls = principalPanel.Controls.Count;
for (int index = 0; index < limitControls; index++)
{
Control control = principalPanel.Controls[0];
control.Dispose();
}
Update();
GC.Collect();
}
private void AddRadFormWindow(Type windowToAdd)
{
if (!principalPanel.Controls.ContainsKey(windowToAdd.Name))
{
var window = (RadForm) Activator.CreateInstance(windowToAdd);
window.TopLevel = false;
window.Visible = true;
window.FormClosing += (method, args) =>
{
radRibbonBarGroupOpenWindows.Items[window.Name + "Button"].Dispose();
GC.Collect();
};
window.Enter += (method, args) => RefreshButtonsChecks(window.Name);
var closeMenuItem = new RadMenuItem("Close");
closeMenuItem.MouseDown += (method, args) =>
{
panelPrincipal.Controls[window.Name].Dispose();
radRibbonBarGroupOpenWindows.Items[window.Name + "Button"].Dispose();
};
var contextMenu = new RadContextMenu();
contextMenu.Items.Add(closeMenuItem);
var button = new RadButtonElement(window.Text) {Name = window.Name + "Button"};
button.MouseDown += (method, args) =>
{
switch (args.Button)
{
case MouseButtons.Left:
if (((RadForm) principalPanel.Controls[window.Name]).WindowState ==
FormWindowState.Minimized)
((RadForm) principalPanel.Controls[window.Name]).Deminimize();
principalPanel.Controls[window.Name].BringToFront();
principalPanel.Controls[window.Name].Focus();
break;
case MouseButtons.Right:
contextMenu.Show(MousePosition);
break;
}
};
radRibbonBarGroupOpenWindows.Items.Add(button);
principalPanel.Controls.Add(window);
principalPanel.Controls[window.Name].BringToFront();
principalPanel.Controls[window.Name].Focus();
}
principalPanel.Controls[windowToAdd.Name].BringToFront();
principalPanel.Controls[windowToAdd.Name].Focus();
Update();
GC.Collect();
}
public Constructor()
{
panelPrincipal.Layout += PanelPrincipalLayout;
}