I am creating a touch application on a no-keyboard pc, where I use a PropertyGrid to manage classes to store / save the app configuration.
I need to edit the propertyline's rows with a custom keyboard that I created (not the system's) setting the class as UITypeEditor
Now the custom keyboard is showed when right button is clicked.
Is it possible to show when on the row start edit (like textbox Enter event),
or when the row is selected ?
The editor control which you see in PropertyGrid is a GridViewEdit control which is a child of PropertyGridView which is a child of the PropertyGrid.
You can find the edit control and assign an event handler to its Enter event. In this event, you can find the SelectedGridItem and then call its EditPropertyValue method which is responsible to show the UITypeEditor.
private void propertyGrid1_SelectedObjectsChanged(object sender, EventArgs e)
{
var grid = propertyGrid1.Controls.Cast<Control>()
.Where(x => x.GetType().Name == "PropertyGridView").FirstOrDefault();
var edit = grid.Controls.Cast<Control>()
.Where(x => x.GetType().Name == "GridViewEdit").FirstOrDefault();
edit.Enter -= edit_Enter;
edit.Enter += edit_Enter;
}
private void edit_Enter(object sender, EventArgs e)
{
var item = this.propertyGrid1.SelectedGridItem;
if (item.GetType().Name == "PropertyDescriptorGridEntry")
{
var method = item.GetType().GetMethod("EditPropertyValue",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance);
var grid = propertyGrid1.Controls.Cast<Control>()
.Where(x => x.GetType().Name == "PropertyGridView").FirstOrDefault();
method.Invoke(item, new object[] { grid });
}
}
Note: For modal editors the Enter event is annoying and repeats over and over again. To avoid this you can use Click event of the control.
Also as another option you can rely on SelectedGridItemChanged event of PropertyGrid and check if e.NewSelection.GetType().Name == "PropertyDescriptorGridEntry" then call EditPropertyValue of the selected grid item using reflection.
Related
I am trying to implement using error provider to validate that my text boxes are not empty before proceeding with execution.
Error provider works on textboxes on the main form but refuses to work on any textbox or combo box that is in a groupbox or tabcontrol. It doesn't check the text boxes, it doesn't display error or waits until the user enter text/select item for the controls that are being checked.
Sure if I loose the groupbox or tabcontrol I would get the error check working as normal but I will also loose the benefit of using the groupbox and tab control for my application as I intended to.
I am using the code below to check if the textbox or combo box is empty/null.
Some help would be much appreciated, this has made me almost want to throw my computer out of the window.
private void button3_Click(object sender, EventArgs e)
{
//Validate the text box in the form before proceeding to store in Database
// var emptyornull = Controls.OfType<TextBox>().Where(box => box.Name.StartsWith("_")).OrderBy(box => box.TabIndex);
// var emptyornull2 = Controls.OfType<ComboBox>().Where(box => box.Name.StartsWith("_")).OrderBy(box => box.TabIndex);
var boxes = Controls.OfType<TextBox>();
foreach (var testControl in boxes)
{
if (string.IsNullOrEmpty(testControl.Text))
{
this.errorProvider1.SetError((Control)testControl, "error");
return;
}
this.errorProvider1.SetError((Control)testControl, (string)null);
}
}
This is because your code does not check the child controls and only checks the top level ones. You need to iterate through the Form's controls recursively:
private IEnumerable<Control> GetAllControls(Control control)
{
var controls = control.Controls.Cast<Control>();
return controls.SelectMany(ctrl => GetAllControls(ctrl)).Concat(controls);
}
private void button1_Click(object sender, EventArgs e)
{
errorProvider1.Clear();
foreach (Control c in GetAllControls(this))
{
if (c is TextBox && string.IsNullOrEmpty(c.Text))
errorProvider1.SetError(c, "Error");
}
}
Or, Linq way:
errorProvider1.Clear();
GetAllControls(this).Where(c => c is TextBox && string.IsNullOrEmpty(c.Text))
.ToList()
.ForEach(c => errorProvider1.SetError(c, "Error"));
Good luck.
This is a question about System.Windows.Forms.Datagrid.
Is it possible to directly move to figure 2 without that "Purchase Details link button" after I click on the Expand Button? I mean I don't want that "Purchase Details link button"
Is that possible?
Legacy DatGrid control has a private NodeClicked event which you can find it using reflection and subscribe for the event. This way you can catch click on a + at row header.
Then you can navigate to the related table of the clicked node using NavigateTo method of DataGrid.
This way, the navigation will be done immediately after you clicked on + at row header.
private void Form1_Load(object sender, EventArgs e)
{
var eventsProperty = dataGrid1.GetType().GetProperty("Events",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance);
EventHandlerList events = eventsProperty.GetValue(dataGrid1) as EventHandlerList;
var eventsNodeClickedKeyField = dataGrid1.GetType().GetField("EVENT_NODECLICKED",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Static);
object eventsNodeClickedKey = eventsNodeClickedKeyField.GetValue(null);
events.AddHandler(eventsNodeClickedKey, new EventHandler(dataGrid1_NodeClicked));
}
private void dataGrid1_NodeClicked(object sender, EventArgs e)
{
var grid = sender as DataGrid;
var point = grid.PointToClient(MousePosition);
var hti = grid.HitTest(point);
grid.NavigateTo(hti.Row, "RelationName");
}
The easiest way would be like #monstertjie_za said. Add a click event to the row, with it open a new form where you can style all the fields to your liking.
optional you can just open the form from figure 2 with the click event.
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.
So I've been able to populate a TreeView with the tabnames in WPF/XAML binding but haven't done this before with C# Windows Forms.
I want to have the treeview display the project name based on what file is open and then tabcontrol names below it (these are static -- one is called editor and the other fields).
I'll add a context menu later, but the sole purpose would be to make the tabs visible based on their state with click events from the treeview.
My problem is I can't figure out how to associate them in the treeview. I found this code, can anyone tell me if I'm on the right track here?
private void treeView1_AfterSelect(Object sender, TreeViewEventArgs e)
{
// Set the visibility of the tabpages from the treeview
if ((e.Action == TreeViewAction.ByMouse))
{
if (e.Node.Name == "Editor")
{
this.editForm.tabControl1.SelectedTab = editForm.Editor;
}
if (e.Node.Name == "Fields")
{
this.editForm.tabControl1.SelectedTab = editForm.Fields;
}
}
}
You could use the TreeNodes's Tag property to hold the associated Tab Name.
if (e.Action == TreeViewAction.ByMouse)
{
TabPage p = tabControl1.TabPages[e.Node.Tag]
tabControl1.SelectedTab = p;
}
Is there a doubleclick event for a datagrid? I'm trying to use this code to open a details form when the user doubleclicks on a row.
http://www.codeproject.com/KB/grid/usingdatagrid.aspx
I tried adding it by doubleclicking on the control, but it gives dataGrid1_Navigate instead.
What you get when you double click a control in design mode is the event the designers of the control thought would be the most used, in this case it's Navigate.
But yes, this control has two double click events:
public partial class Form1 : Form
{
DataGrid grid = new DataGrid();
public Form1()
{
InitializeComponent();
grid.DoubleClick += new EventHandler(grid_DoubleClick);
grid.MouseDoubleClick += new MouseEventHandler(grid_MouseDoubleClick);
grid.Dock = DockStyle.Fill;
this.Controls.Add(grid);
}
void grid_MouseDoubleClick(object sender, MouseEventArgs e)
{
}
void grid_DoubleClick(object sender, EventArgs e)
{
}
}
However, both of these events run when you double click anywhere on the control and they don't directly give you information on what row was selected. You might be able to retrieve the row double clicked in the grid_MouseDoubleClick handler by getting it from the control based on the point being clicked (e.Location), that's how it works in the TreeView control for example. At a quick glance I didn't see if the control has such a method. You might want to consider using DataGridView instead, if you don't have a particular reason to use this control.
Sounds like you need a way to get a list of all the events for a given control, rather than finding the default event (which is what VS gives you when you double click a control in the designer)
There are a few ways of doing this:
One way Select the grid.
Then click the events icon to turn the properties window into a list of events, then doubel click the event you want to strart coding the event.
Alternatively, switch to code view, select the grid in the drop down list of objects at the top left of the code window, then select the event you want from the list of all the events for that control in the event list (top right of the code window)
I tried #steve76's code, but had to tweak it slightly to work in a Windows Embedded CE 6.0 system. Here is what worked for me.
private void dataGrid1_DoubleClick(object sender, EventArgs e)
{
Point pt = dataGrid1.PointToClient(Control.MousePosition);
DataGrid.HitTestInfo info = dataGrid1.HitTest(pt.X, pt.Y);
int row;
int col;
if (info.Column < 0)
col = 0;
else
col = info.Column;
if (info.Row < 0)
row = 0;
else
row = info.Row;
object cellData = dataGrid1[row, col];
string cellString = "(null)";
if (cellData != null)
cellString = cellData.ToString();
MessageBox.Show(cellString, "Cell Contents");
}
Perhaps you can use the DataGridView.CellContentDoubleClick event.
Example:
private void DataGridView1_CellContentDoubleClick(Object sender, DataGridViewCellEventArgs e) {
System.Text.StringBuilder messageBoxCS = new System.Text.StringBuilder();
messageBoxCS.AppendFormat("{0} = {1}", "ColumnIndex", e.ColumnIndex );
messageBoxCS.AppendLine();
messageBoxCS.AppendFormat("{0} = {1}", "RowIndex", e.RowIndex );
messageBoxCS.AppendLine();
MessageBox.Show(messageBoxCS.ToString(), "CellContentDoubleClick Event" );
}
If that is not what you are looking for, you can find other events in the reference:
http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview_events.aspx