I have a RichTextBox created programmatically with the following code:
RichTextBox RT = new RichTextBox();
RT.Name = "asdf";
RT.Text = "blah";
TableLayoutPanel.Controls.Add(RT,0,0);
Now let's say I want to modify the text of RT, and it's name is "asdf", Visual Studio won't allow me to write asdf.Text = "haha" because asdf doesn't exist yet.
How can I grab "asdf" specifically and set its text? Because this RichTextBox is in a specific cell, can I grab it based on its cell coordinates?
You should be able to get a reference to it via the TableLayoutPanel.Controls property, which returns a TableLayoutControlCollection. That class provides two ways to locate a control by name: the Item property and the Find method. The Item property returns a control with the specified name, whereas the Find method returns a collection of controls. In both cases you would need to cast from a Control to a RichTextBox.
var rt = (RichTextBox)myTableLayoutPanel.Controls.Item["asdf"];
// or
var rts = myTableLayoutPanel.Controls.Find("asdf", false);
foreach (var rt in rts)
// (RichTextBox)rt ...
EDIT: be sure to check that the result is not null before using it in case the control is not found.
Well... you did instantiate the RichTextBox and have a reference that you can use; it's called "RT" in your example.
Now, likely you've done this in a method so it was locally scoped and is no longer available when you want it. So you save that reference somehow by assigning it to some member you can access. If you have a lot of them and want to differentiate by name somehow, you might stick it into a Dictionary<string, RichTextBox>, for example. Or you could put it in some static variable; there are numerous options, each with their own pros and cons.
The one thing you probably don't want to do is walk the control tree looking for the control with the name you specified. But you could also do that, if you really wanted to.
Related
I'm in the middle of trying to transfer VBA code over to C# so that form application I made is standalone. I'm having issues with trying to get the text from a shape that is within a shape(in a group). Here is an example in VBA that works flawless.
Dim text as String
text = groupShape.shapes.item("rectangle").text
This is returning the correct value.
In C# I am using the microsoft.office.interop.visio.dll reference. I've been able to read in shape names just fine so I know I have the application and document objects working fine. In C# the code above looks like:
var text = "";
text = Doc.Shapes.ItemU("groupShape").Shapes.ItemU("rectangle").text
This is not returning the correct value. It is saying that it will return "Object" so I believe its not returning a string but an object.
What can I do to solve this in order to return the text? Thanks!
EDIT:
Here is the actual code I am writing. The vba and the c#
VBA:
Dim tempShape As Shape
Set tempShape = ActiveDocument.Pages(pageName).Shapes.Item("MainTable")
txtJobName.value = tempShape.Shapes.Item("textJobName").Text
c#
IVisio.Shape tempShape = Doc.Pages[Loaded_Page.Name].Shapes.ItemU["MainTable"];
Txt_JobName.Text = tempShape.Shapes.ItemU["textJobName"].Characters.Text;
ANOTHER EDIT:
I've also tried going into the shape data properties by referencing the cell that the text is in and still no luck.
Txt_JobName.Text = tempShape.Shapes.ItemU["textJobName"].CellsSRC[8, 0, 0].ResultStr[0];
First, try using , .Item not .ItemU, those two are different functions. The default one (one that you are using implicitly in VBA) is Item. You may be actually addressing a different shape in c#
Second, .Text should be starting with capital T, the code with small t should not compile. Make sure that .text in lowercase is not an extension method you imported from somewhere, (unrelated to Visio)
Third caveat - to make sure to get text from shape as you see it in UI, it is better to use shape.Characters.Text, because in case shape contains fields, the shape.Textwill return placeholders ('obj') for those places where the field text should go. But this applies to both VBA and C#
Fourth.. groupShape in VBA appears to be a variable name, not shape name. From the code it's not clear what is the name of that group shape. How do you get that one in VBA? May be worth checking.
I'm not very familiar with the Visio type library, but this:
groupShape.shapes.item("rectangle")
Is returning a Shape object. Grab that object reference instead of discarding it with another dot. VBA is being "helpful" here, and happily lets you write late-bound calls that will only be resolved at runtime - C# will only be that permissive with the dynamic keyword, and you typically don't want to code against dynamic - you want to work with strong types:
Dim rectangle As Shape
Set rectangle = groupShape.shapes.item("rectangle")
Dim rectangleText As String
rectangleText = rectangle.Text
The C# / interop code needs to do the same:
var groupShape = (Shape)Doc.Shapes.ItemU("groupShape");
var rectangle = (Shape)groupShape.Shapes.ItemU("rectangle");
var rectangleText = rectangle.Text // assuming Text is defined on the Shape interface
In other words, always be aware of the types you're working with; if a member returns an object and you need it to be a more specific type, you need to cast as appropriate before you can have compile-time validation of the member call, or cast to dynamic if you don't care for compile-time validation and defer them to run-time:
var text = (string)((dynamic)groupShape.Shapes.ItemU("rectangle")).Text
Notice the cast to string; text will be a string. Forget that cast and your code will have to deal with dynamic spreading throughout the execution paths like a cancer and ruining your type safety - and you don't want that.
As always, I come to find out the reason the .Text was returning "Obj" is that the shape did not have any text in it. If there is text, it will return it. I got too caught up into the return, "Obj". I wonder why it doesn't return empty text or null if there is no text in the shape. Anyways, all the other answers on this question are very helpful and they lead me to finding my problem.
I have a control which is a TreeView node that will always be set to the name of the PC you're currently running the tested software on. Therefore I need the Search Property for the control's Name property to be set to `Environment.MachineName like so:
The problem with this is that inside UIMap.Designer.cs I can see the generated code that this makes and it's trying to use Environment.MachineName as a string:
this.SearchProperties[WinTreeItem.PropertyNames.Name] = "Environment.MachineName";
Obviously this approach won't work, and it's not possible to manually edit UIMap.Designer.cs to change this. How can I make this work then?
The general approach is to use the UI Map editor to remove that search item. This should be possible from the window shown in the question. Then, in the test method that needs to do the search, add a statement something like
this.uimap.controlNames.SearchProperties[WinTreeItem.PropertyNames.Name]
= Environment.MachineName;
or
this.uimap.controlNames.SearchProperties.Add(name, Environment.MachineName;
The precise statement depends on the structure of the controls, so where I wrote .controlNames. it may need a series of dot-separated control names.
My concern is mainly to use Contains method of List (I think the best way to do checking).
Controls: Spinner, EditText and Button(for checking)
In my resources(String.xml) I created a string-array of name = "Fruits".
In my Activity1.cs I also created an ArrayAdapter to populate the items of my string-array and assigned it to my spinner.adapter object.
var spinner = FindViewById<Spinner>(Resource.Id.spinner1);
var adapter = ArrayAdapter.CreateFromResource(this, Resource.Array.Fruits, Android.Resource.Layout.SimpleSpinnerDropDownItem);
spinner.Adapter = adapter;
Note: The text found on the EditText control is equal to the selected item on the spinner control BUT I also allow the user to enter it manually.
Questions:
If this is possible, how can I convert ArrayAdapter to List type. (My main purpose is to make use of the Contain method in w/c I am checking the inputted data from EditText if found on the List)
Is there any other way to check data out from the string-array resource? (Note: I don't want to use any loop just to check only 1 item on the program if it exist. Just let .net do the rest for me.)
One easy way would be to just load the string array yourself into memory and check there:
string[] fruits = Resources.GetStringArray(Resource.Array.Fruits);
var containsOrange = fruits.Contains("orange");
Make sure you have the System.Linq namespace included in order to get the Contains() method.
I am using DevExpress Components controls.I want to create controls from string Value
like "DevExpress.XtraEditors.TextEdit".I know I can make this with reflection like
var textBoxType = typeof(Control).Assembly.GetType("System.Windows.Forms.TextBox", true);
var textBox = Activator.CreateInstance(textBoxType);
I want to make this for write little code.but DevExpress have a lot of namespace and class.
Can I create control from string unless give A MainClass? (like my sample code typeof(Control))
if I can not make I have to use alot of if
You need to know which assembly the class is defined in.
For example, all of the editors are in DevExpress.XtraEditors.vX.Y.dll, or typeof(BaseEdit).Assembly.
If you don't know which assembly it's defined in, you can create a collection of DevExpress assemblies (typeof(GridControl).Assembly, typeof(TreeList).Assembly, ...) and loop through them until asm.GetType(name) doesn't return null.
Note that it will be very slow.
In the project I have some custom WebUserControls for form elements (they encapsulate some standard validators and other system specific functions). My user controls are "DropDownListField" and "TextBoxField". In the code behind of a page I have this code:
string parameterValue = null;
foreach (object control in myMultiView.Views[myMultiView.ActiveViewIndex].Controls)
{
if (control.GetType() == typeof(DropDownListField))
parameterValue = ((DropDownListField)control).Value;
if (control.GetType() == typeof(TextBoxField))
parameterValue = ((TextBoxField)control).Value;
}
For some reason the "if" statements always return false even when I step through the code and see that "control" is getting assigned my web user control. This code is in another place in the project exactly the same except in the other location the standard .net controls "TextBox" and "DropDownList" are used and in the other location the code works.
Does anybody know why this wouldn't work with web user controls?
UPDATE:
Hmm so in debugging I found this:
?control.GetType();
BaseType: {Name = "DropDownListField" FullName = "WebUI.UserControls.Fields.DropDownListField"}
?typeof(DropDownListField);
BaseType: {Name = "UserControl" FullName = "System.Web.UI.UserControl"}
So typeof is just recognizing they are user controls not the full type it seems.
Does anybody know how I would check for a specific user control type?
I'm guessing they aren't the same type, use debugging to find out the actual type.
Also, try using the 'is' keyword instead.
PS: It might be cleaner for you to say if (control is DropDownListField)
I don't recall if a view directly includes its children in Controls, but I wouldn't be surprised if Controls contained only one element, which would be a container of some sorts. Therefore, your controls are potentially in Controls[0].Controls or even further down. I would advise you create a method that finds the child recursively.
Actually, your controls should all implement a common interface (example:
interface ICustomFieldWithValue { string Value {get; set; }}
). Your resulting code would be much cleaner.
c2.GetType().ToString() == "System.Web.UI.WebControls.Label"