I have a telerik grid view and when I right click the header, I'm showing a with a ListBox inside containing the list of columns.
The item template is redefined to show a check box so I can set the column visible or not.
I can also drag/drop columns to reorder them.
So here is how I create my Popup:
var view = new ColumnsOrderer.ColumnsOrderer
{
DataContext = new ColumnsOrderer.ViewModelColumnsOrderer(Columns)
};
var codePopup = new Popup
{
Child = view,
MaxHeight = 400,
StaysOpen = false,
Placement = PlacementMode.Mouse
};
codePopup.IsOpen = true;
Now everything seems to work correctly, but it's not.
If I set columns visible or hidden and then click outside the popup, it closes correctly.
Though if I drag an item to reorder it, the popup seems to lose focus and then it won't close if I click outside the popup. I have to click back in the list box inside the popup and then it closes by clicking outside.
Here is my drag/drop events:
public ColumnsOrderer()
{
InitializeComponent();
InitialiazeListBoxDragDrop();
}
private void InitialiazeListBoxDragDrop()
{
var itemContainerStyle = new Style(typeof(ListBoxItem));
itemContainerStyle.Setters.Add(new Setter(AllowDropProperty, true));
itemContainerStyle.Setters.Add(new EventSetter(PreviewMouseMoveEvent, new MouseEventHandler(OnMouseMove)));
itemContainerStyle.Setters.Add(new EventSetter(DropEvent, new DragEventHandler(OnDrop)));
listColumns.ItemContainerStyle = itemContainerStyle;
}
void OnMouseMove(object sender, MouseEventArgs e)
{
if (e.OriginalSource is CheckBox || e.LeftButton == MouseButtonState.Released)
return;
if (sender is ListBoxItem)
{
var draggedItem = sender as ListBoxItem;
draggedItem.IsSelected = true;
DragDrop.DoDragDrop(draggedItem, draggedItem.DataContext, DragDropEffects.Move);
}
}
void OnDrop(object sender, DragEventArgs e)
{
if (!(sender is ListBoxItem))
return;
}
An interesting thing is that if I remove the OnDrop handler, the problem is not there.
I tried many ways to set back the focus to the popup, but it's not working.
Could anyone help me on that?
How about trying to re-focus your Popup control after the drag and drop operation?
void OnDrop(object sender, DragEventArgs e)
{
if (!(sender is ListBoxItem))
return;
codePopup.Focus();
}
Related
I have many forms with a lot of textboxes. And I want to add to that forms a button with IsDefault = true. Then fill any property and press enter. If I will not set UpdateSourceTrigger=PropertyChanged on textbox, it will not see my input.
The problem is that I do not want to add UpdateSourceTrigger=PropertyChanged to each textbox, combobox, checkbox, and etc.
Is there any way to trigger everything to write it's data to the source without adding UpdateSourceTrigger=PropertyChanged?
Call the BindingExpression.UpdateSource method in the click event handler for each of the Controls (TextBox, CheckBox, etc.) that you have in your Window/UserControl, like this:
private void ButtonBase_OnClick(object sender, RoutedEventArgs e) {
this.UpdateSourceTrigger(this);
MessageBox.Show($"Field1: {this.vm.Field1}\nField2: {this.vm.Field2}\nField3: {this.vm.Field3}");
}
public void UpdateSourceTrigger(UIElement element) {
if (element == null) return;
var children = LogicalTreeHelper.GetChildren(element);
foreach (var e in children) {
if (e is TextBox txtBox) {
var binding = txtBox.GetBindingExpression(TextBox.TextProperty);
binding?.UpdateSource();
}
if (e is CheckBox chkBox) {
var binding = chkBox.GetBindingExpression(CheckBox.IsCheckedProperty);
binding?.UpdateSource();
}
// add other types, like ComboBox or others...
// ...
this.UpdateSourceTrigger(e as UIElement);
}
}
I need to show a view on a click of a button. This is the code for the event Click
private void Button_Click(object sender, RoutedEventArgs e)
{
Button s = sender as Button;
//some stuff needed to recognise which button was pressed
myPopup.PlacementTarget = s;
myPopup.Placement = System.Windows.Controls.Primitives.PlacementMode.Top;
myPopup.IsOpen = true;
}
this is the element defined in xaml
<Popup IsOpen="False" StaysOpen="True" Name="myPopup">
<view:myCustomView />
</Popup>
I have 2 problem with this.
1- The background of my view is black, even if i didn't set it (i think it should be transparent?)
2- When i click anywhere inside the Popup, this simply disappear
Which is the proper way to show my view? I don't want to bind anything of the ViewModel that own the button to this new view, which has his own viewmodel
Note that on the event Button_Click i will send some parameters to the ViewModel of myCustomView that will change some of its functionality (that's why i need to create a new instance of the view every time the Button_Click event is fired)
EDIT 1: Thanks to the answer of EdPlunkett i was able to solve the problem with the background. I just need to set AllowsTransparency="True"
EDIT2:
I defined my Popup via Code Behind as suggested, so my code now is:
private void Button_Click(object sender, RoutedEventArgs e)
{
Button s = sender as Button;
System.Windows.Controls.Primitives.Popup popup = new System.Windows.Controls.Primitives.Popup();
popup.AllowsTransparency = true;
popup.Child = new myCustomView();
popup.PlacementTarget = s;
popup.Placement = System.Windows.Controls.Primitives.PlacementMode.Top;
popup.IsOpen = true;
popup.StaysOpen = true;
}
The problem is, that when i click inside any of the controls defined inside myCustomView, the Popup lose the focus and close.
I suspect that the Popup is defined inside another Popup like for example the dropdown of a ComboBox, right?
You could try to create the Popup element programmatically in the click event handler:
private void Button_Click(object sender, RoutedEventArgs e)
{
Button s = sender as Button;
System.Windows.Controls.Primitives.Popup popup = new System.Windows.Controls.Primitives.Popup();
popup.AllowsTransparency = true;
popup.Child = new myCustomView();
//some stuff needed to recognise which button was pressed
popup.PlacementTarget = s;
popup.Placement = System.Windows.Controls.Primitives.PlacementMode.Top;
popup.IsOpen = true;
popup.StaysOpen = true;
}
This should let you click within the pop up view without the Popup being closed. Make sure that the view has a Background set:
popup.Child = new myCustomView() { Background = Brushes.White };
I tried your solution, and while it's true that the situation is slightly better, i still have the closing problem. I can click inside the Popup without this being closed, but when i click inside any of the textbox that i defined inside my view, the Popup close
So set the PlacementTarget to the parent ItemsControl and then set the VerticalOffset and HorizontalOffset properties of the Popup to specify its exact location on the screen, e.g.:
private void btn_Click(object sender, RoutedEventArgs e)
{
Button s = sender as Button;
System.Windows.Controls.Primitives.Popup popup = new System.Windows.Controls.Primitives.Popup();
popup.AllowsTransparency = true;
popup.Child = new myCustomView();
//some stuff needed to recognise which button was pressed
popup.PlacementTarget = ic; //<-- "ic" is the name of the parent ItemsControl
Point p = s.TranslatePoint(new Point(0, 0), ic);
popup.VerticalOffset = p.Y;
popup.HorizontalOffset = p.X;
popup.IsOpen = true;
popup.StaysOpen = true;
}
You should adjust the values of the VerticalOffset and HorizontalOffset to fit your requirements.
I have a c# winform with tabControl (it has 5 Tabs), textboxes, datetimepicker and checkboxes, connected via Entity Framework to a table.
All my checkboxes have their property Checked set to False, CheckState set to Unchecked and ThreeState set to False.
When I'm adding a new record, my checkboxes encounter a very strange behaviour. At adding a new record, my program calls a subroutine called EmptyCheckBoxes to make sure, that they are all set to false and their texts are set to "Ne". So far so good --> they are set to false and texts are correct(see image1).
Here are 2 scenarios with my problem:
1.
I click one checkbox to make him checked (set to true and set its text to "Da" --> look at Ponedeljek on image2). Till here, everything went as planned.
But, if I use my mouse and try click other checkbox (look at Torek on image3), this checkbox remains unchecked and all other checkboxes on my form have become grayed and checked!
2.
At adding a new record checkboxes are set to false and texts are correct(see image1). But, this time I'm not going to touch my checkboxes, I just click into my datetimepicker and then into some other textbox. Bam!
All checkboxes on my form have become grayed and checked!
How can this be, if their ThreeState property is set to False?
This is really annoying and I'm totaly lost, where to look to find the cause of this problem. Because, if I save this new record, all checkboxes lose their gray color and stay checked with texts "Ne" (values true are saved into table!).
All checkboxes have this code (this is from one of them):
private void checkBox49_Click(object sender, EventArgs e)
{
if (checkBox49.Checked == true)
{
checkBox49.Text = "Da";
}
else
{
checkBox49.Text = "Ne";
}
}
private void checkBox49_CheckedChanged(object sender, EventArgs e)
{
if (checkBox49.Checked == true)
{
checkBox49.Text = "Da";
}
else
{
checkBox49.Text = "Ne";
}
}
This is a code for setting checkboxes to false and texts to "Ne":
private void EmptyCheckBoxes()
{
TabPage tabPage1 = tabControl1.TabPages[0];
TabPage tabPage2 = tabControl1.TabPages[1];
TabPage tabPage3 = tabControl1.TabPages[2];
TabPage tabPage4 = tabControl1.TabPages[3];
TabPage tabPage5 = tabControl1.TabPages[4];
tabControl1.SelectedTab = tabPage1;
UncheckCheckBoxes(tabPage1);
tabControl1.SelectedTab = tabPage2;
UncheckCheckBoxes(tabPage2);
tabControl1.SelectedTab = tabPage3;
UncheckCheckBoxes(tabPage3);
tabControl1.SelectedTab = tabPage4;
UncheckCheckBoxes(tabPage4);
tabControl1.SelectedTab = tabPage5;
UncheckCheckBoxes(tabPage5);
}
private void UncheckCheckBoxes(Control ctrl)
{
CheckBox chkBox = ctrl as CheckBox;
if (chkBox == null)
{
foreach (Control child in ctrl.Controls)
{
UncheckCheckBoxes(child);
}
}
else
{
chkBox.Checked = false;
chkBox.Text = "Ne";
}
}
Thank you for any hint, clue or solution to this problem.
Vladimir
Fabio, you were right about _Click eventhandler. But it did not solve my problem.
My problem are causing groupboxes on my winform. Why, I don't know.
This is my workaround for CheckStateChanged event that works like charm:
private void My_checkBox_CheckStateChanged(object sender, EventArgs e)
{
if (_addnew == true)
{
CheckBox my_cb = (CheckBox)sender;
if ((my_cb.CheckState == CheckState.Indeterminate) && (my_cb.Text == "Da"))
{
my_cb.Checked = false;
my_cb.Text = "Ne";
}
}
}
I Have a textbox which is disabled and has value .And i want to enable right click option to copy the disabled value from textbox (Windows application).Pls help me to do this.
Try this, keeping in mind that you have to have your contextmenustrip added:
private void YourFormName_Load(object sender, EventArgs e)
{
ContextMenu mnu = new ContextMenu();
MenuItem mnuCopy = new MenuItem("Copy");
mnuCopy.Click += (sen, ev) =>
{
System.Windows.Forms.Clipboard.SetText(YourTextBoxName.Text);
};
mnu.MenuItems.AddRange(new MenuItem[] { mnuCopy });
YourTextBoxName.ContextMenu = mnu;
}
private void YourFormName_MouseUp(object sender, MouseEventArgs e)
{
Control ctl = this.GetChildAtPoint(e.Location);
if (ctl != null && !ctl.Enabled && ctl.ContextMenu != null)
ctl.ContextMenu.Show(this, e.Location);
}
When you click on a disabled element in a page, the event is handled by the parent element of the disabled element.
for example if your textbox is in a page then the page handles it. if the text box is in a different container like div, then that container will handle the mouse click event.
for your situation, you could write a handler on the parent element.
a javascript function that will catch the event and it can read the value for you. for instance, the JS function can change the disabled property to false, read the value, and then disable the textbox again.
Coming back to Vijaya's answer, I handled the problem by just placing the control with Dock=Fill into a panel control with zero padding and margin. So you would do your things in the MouseUp event of the panel instead.
I'm creating a ToolStripMenu shown below that is supposed to allow the user to interact with the items "XML" and "Non XML" as though they are regular check boxes on a form. However, when one item is checked/unchecked the menu closes. How can I allow an item to be checked/unchecked without closing the menu? Or is there a different standard method of achieving the same behavior?
So what I want is to be able to click on "Non XML", show a check box and leave the menu open.
The idea is that the last menu item will be "Done" and when it's clicked the "G2S" sub items will remain open but the "Display" sub items ( XML, Non XML ) will close.
Any ideas?
Note: I am aware that this is likely not the best user interface design. I'd like to know however how this could be accomplished just to gain some technical knowledge about handling menus.
Interesting concept is described in this thread on Stackoverflow:
Here is the essence of the accepted answer:
ParentMenu.DropDown.AutoClose = false;
It does exactly what you are asking for - prevent menu from closing when subitem is clicked.
Here's a useful extension that requires user to click outside of menu item + dropdowns to close.
public static void KeepOpenOnDropdownCheck (this ToolStripMenuItem ctl)
{
foreach (var item in ctl.DropDownItems.OfType<ToolStripMenuItem>())
{
item.MouseEnter += (o, e) => ctl.DropDown.AutoClose = false;
item.MouseLeave += (o, e) => ctl.DropDown.AutoClose = true;
}
}
Posted in case somebody finds it helpful.
Instead of trying to do exactly what I had originally intended, I've come up with the following:
1- Use a ContextMenuStrip
2- When the user clicks on the ToolStripMenu item I display the ContextMenuStrip at a location near the menu item as shown below: ( note the positioning still needs adjusting )
To get this working I build the ContextMenuStrip in code at run-time so that the items in the ContextMenuStrip can be build dynamically based on the situation.
Code snippets:
Show the ContextMenuStrip when the menu item is clicked:
private void filterToolStripMenuItem_Click(object sender, EventArgs e)
{
contextMenuStrip1.Show(this, 180, 20);
}
Build the ContextMenuStrip:
if (protInfo.Name == "QCOM" )
{
BroadCast = new CheckBox();
BroadCast.Text = "Date/Time Broadcast";
BroadCast.Checked = FlagSet(CurrentFilter, (Byte)Filter.DateTimeBC);
ToolStripControlHost Ch1 = new ToolStripControlHost(BroadCast);
GenPoll = new CheckBox();
GenPoll.Text = "Status Poll";
GenPoll.Checked = FlagSet(CurrentFilter, (Byte)Filter.GenStatusPoll);
ToolStripControlHost Ch2 = new ToolStripControlHost(GenPoll);
GenPollResp = new CheckBox();
GenPollResp.Text = "Status Poll Response";
GenPollResp.Checked = FlagSet(CurrentFilter, (Byte)Filter.GenStatusResponse);
ToolStripControlHost Ch3 = new ToolStripControlHost(GenPollResp);
Button btnDone = new Button();
btnDone.Text = "Done";
ToolStripControlHost Ch4 = new ToolStripControlHost(btnDone);
btnDone.Click += new EventHandler(btnDone_Click);
contextMenuStrip1.Items.Clear();
contextMenuStrip1.Items.Add(Ch1);
contextMenuStrip1.Items.Add(Ch2);
contextMenuStrip1.Items.Add(Ch3);
contextMenuStrip1.Items.Add(Ch4);
contextMenuStrip1.Enabled = true;
filterToolStripMenuItem.Enabled = true;
}
else
{
filterToolStripMenuItem.Enabled = false;
}
This may not be the best user interface design, but it seems to work.
The original solution will work with the use of mouse events.
On mouse enter event:
parent.dropdown.autoclose = false;
on mouse leave event:
parent.dropdown.autoclose = true;
The only catch is if the user access the menu items by other means than a mouse.
I used a combination of Neolisk's and Chimera's answers to allow deletion of multiple leaf items from a treeview. My solution is below
Note: the following Items created at design time are used:
TreePromotions (TreeView)
menuVendorSection (Context Menu Strip)
removeMultipleItemsToolStripMenuItem (DropDown of menuVendorSection)
private void removeMultipleItemsToolStripMenuItem_MouseHover(object sender, EventArgs e)
{
removeMultipleItemsToolStripMenuItem.DropDownItems.Clear();
ToolStripMenuItem detailMenuItem;
TreeNode vendorSectionNode = treePromotions.SelectedNode;
for (int vsn = 0; vsn < vendorSectionNode.Nodes.Count; vsn++)
{
//add checkbox item
detailMenuItem = new ToolStripMenuItem(vendorSectionNode.Nodes[vsn].Text);
detailMenuItem.Tag = vendorSectionNode.Nodes[vsn].Tag;
detailMenuItem.CheckOnClick = true;
removeMultipleItemsToolStripMenuItem.DropDownItems.Add(detailMenuItem);
}
//add action buttons
Button buttonDeleteMultiple = new Button();
buttonDeleteMultiple.Text = "Remove Checked Items";
ToolStripControlHost buttonHost = new ToolStripControlHost(buttonDeleteMultiple);
buttonDeleteMultiple.Click += new EventHandler(buttonDeleteMultiple_Click);
removeMultipleItemsToolStripMenuItem.DropDownItems.Add(buttonHost);
Button buttonCancelMultipleDelete = new Button();
buttonCancelMultipleDelete.Text = "CANCEL";
buttonHost = new ToolStripControlHost(buttonCancelMultipleDelete);
buttonCancelMultipleDelete.Click += new EventHandler(buttonCancelMultipleDelete_Click);
removeMultipleItemsToolStripMenuItem.DropDownItems.Add(buttonHost);
removeMultipleItemsToolStripMenuItem.DropDown.AutoClose = false;
menuVendorSection.AutoClose = false;
}
private void buttonDeleteMultiple_Click(object sender, EventArgs e)
{
//delete items
for (int dmi = 0; dmi < removeAllItemsToolStripMenuItem.DropDownItems.Count - 2; dmi++) //do not include buttons
{
((Detail)removeAllItemsToolStripMenuItem.DropDownItems[dmi].Tag).Delete(); //deletes item from database
}
//rebuild leaf
treePromotions.SelectedNode.Nodes.Clear();
addItemNodes(treePromotions.SelectedNode); //builds leaf nodes from database
//close menus
removeMultipleItemsToolStripMenuItem.DropDown.Close();
menuVendorSection.AutoClose = true;
menuVendorSection.Close();
}
private void buttonCancelMultipleDelete_Click(object sender, EventArgs e)
{
//just close menus
removeMultipleItemsToolStripMenuItem.DropDown.Close();
menuVendorSection.AutoClose = true;
menuVendorSection.Close();
}
If someone is still interested, here is a vb solution:
1) For the parent tool strip menu item, add the following handler in the form's constructor:
AddHandler ParentTSMI.DropDown.Closing, AddressOf onDropDownClosing
2) The handler:
Private Sub onDropDownClosing(sender As Object, e As ToolStripDropDownClosingEventArgs)
If e.CloseReason = ToolStripDropDownCloseReason.ItemClicked Then
e.Cancel = True
End If
End Sub
That's it all.
Don't forget to remove the handler (RemoveHandler) when you close the form.