I'm making a button to create a SOOrder from the Project. I'd like to write the newly created number back to the project, so I've added a custom field for that. It's on the form and the whole process works great.
That said, at the end when I try to write back to the project I get the following error any time I try to reference PMProjectExt:
error CS0246: The type or namespace name 'PMProjectExt' could not be found (are you missing a using directive or an assembly reference?)
Ideally my update line looks like this Base.Caches[typeof(PMProject)].SetValue<PMProjectExt.usrTEKSOOrderNbr>(TheRow, header.OrderNbr);
But even something as simple as declaring a variable (eg PMProjectExt testExt; with the PMProjectExt gets the same error.
I'm sure I'm doing something really stupid, but I can't seem to resolve it.
If you want to update a project, I recommend to instantiate the PMProject graph, assign the current record & update the user-field value. Finally persist the changes to the graph. Something like this.
ProjectEntry graph = PXGraph.CreateInstance<ProjectEntry>();
PMProject currentProject = graph.Project.Search<PMProject.contractCD>(Base,[your project nbr])
if (currentProject!=null)
{
graph.Project.Current = currentProject;
PMProjectExt projectExtension = PXCache<PMProject>.GetExtension<PMProjectExt>(currentProject);
projectExtension.usrTEKSOOrderNbr = "ABC123";
graph.Actions.PressSave();
graph.Clear();
}
So, turns out that Projects used to be Contracts. So to get the extension on Projects you need to use contracts like this:
PMProject TheRow = (PMProject)e.Row;
ContractExt TheExt = PXCache<Contract>.GetExtension<CT.ContractExt>(TheRow);
string refNbr = TheExt.UsrTEKSOOrderNbr;
Related
I started working with CodedUI few months before to automate a desktop Application(WPF).
Just checking out for the best ways to create a framework for my Application.
As, I have seen in other automation tools, I feel the heart of an automation framework using any tool(UI Based) is the way it's object Repository is created i.e. how well the UI objects are defined. A Cleaner and well defined Object Repository always proves to be very helpful when it comes to updating your tests.
I am trying to discover the best way to store my UIObjects so that in case of any UI changes in my Application, I have to put minimum effort to update my automation test.
Also, If an Object changes in application, updating it only at one place should solve the problem.
This can be any kind of change like :
->change in just a property(This I feel would be very easy to update in automation Test. The best and Easiet way I feel is to simply update the .uitest file(the xml file) if possible.)
->change in hierarchy and position
->entirely new object added
For the 2nd and 3rd changes, updating scripts become a difficult job, esp if the UIObject is being referred at may places, in many TestMethods, or Modules.
Also, I have generally seen that in Test Methods, Variable Declarations are done to create a reference to the UIMap objects and those variables are further used in the TestMethod Code.
So, in this case If the UI of my application changes, I will have to update the variable decalaration in each of the Test Methods. I want to reduce this effort to changing the variable decalaration only at one place. OfCourse, I cannot have all the code inside only one Test Method. One way that came to my mind is as:
Can't I have simply one common place for all these Variable decalarations. We can give a unique and understandable name to each UIObject e.g.: The decalratoions will look like:
UITabPage UITabPage = this.UIMap.UISimWindow.UISelectEquipmentTabList.UITabPage;
WpfRow UIRow = this.UIMap.UISimWindow.UISelectEquipmentTabList.UITabPage.UIEquipmentDetailsTable.UIRow;
WpfText UIEquipmentTagText = this.UIMap.UISimWindow.UISelectEquipmentTabList.UITabPage.UIEquipmentDetailsTable.UIRow.UITagCell.UIEquipmentTagText;
WpfCheckBox UIEquipmentCheckBox = this.UIMap.UISimWindow.UISelectEquipmentTabList.UITabPage.UIEquipmentDetailsTable.UIRow.UICheckBoxCell.UICheckBox;
....
....
and use these variables wherever required. Hence, In case of any chnages also, there will be only one place where you will need to update thse objects.
But for this, These varaibles must be made STATIC. What can be problem with making these Object Variables static?
Please provide your suggestion on this topic. May be what I am thinking is not possible or practical. I just want to choose the best way to start with before I go too far with the automation scripts and realize later that my approach wasn't a good one.
Thanks in Advance,
Shruti
Look into using descriptive programming instead of using the UIMaps.
Make a static class with generic functions to assist. Going to give you some examples of how to set it up.
For example:
public WinWindow parentwin(string ParentControlName)
{
var parentwin = new WinWindow();
parentwin.SearchProperties.Add("Control Name", ParentControlName);
return parentwin;
}
public WinWindow childwin(string ChildWinControlName, string ParentControlName)
{
var childwin = new WinWindow(parentwin(ParentControlName));
childwin.SearchProperties.Add("Control Name", ChildWinControlName);
return childwin;
}
public WinButton button(string ButtonName,string ChildWinControlName, string ParentControlName)
{
var childwin = childwin(ChildWinControlName,ParentControlName);
var button = new WinButton(childwin);
button.SearchProperties.Add("Name", ButtonName);
}
public void ClickButton(string ButtonName,string ChildWinControlName, string ParentControlName)
{
var button = button(ButtonName,ChildWinControlName,ParentControlName);
Mouse.Click(button);
}
public void ChangeFocus(WinWindow NewFocus)
{
var NewFocus = new NewFocus();
NewFocus.SetFocus();
}
public void ChangeFocus(WinWindow NewFocusChild, string c)
{
var a = new NewFocus();
a.SetFocus();
}
ChangeFocus(childwin("WelcomeForm", "MainForm");
ClickButton("&OK", "WelcomeForm", "MainForm");
I have an Excel Vsto addin application in which I host WPF application build using Calibrun Micro Autofac.I have a dialog popping up the excel and I want that Pop up window's Owner to be set to this excel window.Only way I see doing this is using WindowInteropHelper Class which needs Window instance.
And I am using settings like this :
dynamic settings = new ExpandoObject();
And I show window like this :
windowManager.ShowDialog(viewModel, settings: settings);
So What should I do to set the settings.Owner Property to this excel window(Whose Handle is known) so that the Pop up window is always on top of excel window??
It looks like you are hosting a WPF application (add-in) inside Excel which is an Office application and Caliburn.Micro has a constructor in BootstrapperBase class exactly for this situation, it looks like this: BootstrapperBase(useApplication = true), so you should derive your bootstrapper from BootstrapperBase and pass in false to the base constructor. something like this:
class MyBootstrapper : BootstrapperBase {
MyBootstrapper()
: base(false)
{
}
}
Then Caliburn.Micro will set the owner property correctly for you, you don't have to worry about it. Now if you knew about this but it didn't work for then comment on this and i will give you a solution specific to your situation.
Edit: To set the owner of the created window we need to set the Owner property (which is of type Window) but the problem is that you are working with a native win32 window so you only have a handle and WPF windows don't accepts handles as Owners, and the second problem is that we don't have a reference to the created window so we can wrap it inside a WindowInteropHelper, in order to solve this i suggest the following:
Add information to the created window so we can identify it later, we can do it like this:
var settings = new ExpandoObject();
settings.Tag = "THE_ONE"
windowManager.ShowDialog(viewModel, settings: settings);
After doing so we need to get a reference to that window, so we can
do something like this: var ourWindow = Application.Current.Windows.FirstOrDefault(w => w.Tag == "THE_ONE");
Now we wrap that with a WindowInteropHelper like this: var
interopHelper = new WindowInteropHelper(ourWindow);
Now we can set owner to the native window handle like this:
interopHelper.Owner = (IntPtr) //
PUT_YOUR_NATIVE_WINDOW_HANDLE_HERE;
That's all i can help you with, i hope it works.
After spending a year working with the Microsoft.Xrm.Sdk namespace, I just discovered yesterday the Entity.FormattedValues property contains the text value for Entity specific (ie Local) Option Set texts.
The reason I didn't discover it before, is there is no early bound method of getting the value. i.e. entity.new_myOptionSet is of type OptionSetValue which only contains the int value. You have to call entity.FormattedValues["new_myoptionset"] to get the string text value of the OptionSetValue.
Therefore, I'd like to get the crmsrvcutil to auto-generate a text property for local option sets. i.e. Along with Entity.new_myOptionSet being generated as it currently does, Entity.new_myOptionSetText would be generated as well.
I've looked into the Microsoft.Crm.Services.Utility.ICodeGenerationService, but that looks like it is mostly for specifying what CodeGenerationType something should be...
Is there a way supported way using CrmServiceUtil to add these properties, or am I better off writing a custom app that I can run that can generate these properties as a partial class to the auto-generated ones?
Edit - Example of the code that I would like to be generated
Currently, whenever I need to access the text value of a OptionSetValue, I use this code:
var textValue = OptionSetCache.GetText(service, entity, e => e.New_MyOptionSet);
The option set cache will use the entity.LogicalName, and the property expression to determine the name of the option set that I'm asking for. It will then query the SDK using the RetrieveAttriubteRequest, to get a list of the option set int and text values, which it then caches so it doesn't have to hit CRM again. It then looks up the int value of the New_MyOptionSet of the entity and cross references it with the cached list, to get the text value of the OptionSet.
Instead of doing all of that, I can just do this (assuming that the entity has been retrieved from the server, and not just populated client side):
var textValue = entity.FormattedValues["new_myoptionset"];
but the "new_myoptionset" is no longer early bound. I would like the early bound entity classes that gets generated to also generate an extra "Text" property for OptionSetValue properties that calls the above line, so my entity would have this added to it:
public string New_MyOptionSetText {
return this.GetFormattedAttributeValue("new_myoptionset"); // this is a protected method on the Entity class itself...
}
Could you utilize the CrmServiceUtil extension that will generate enums for your OptionSets and then add your new_myOptionSetText property to a partial class that compares the int value to the enums and returns the enum string
Again, I think specifically for this case, getting CrmSvcUtil.exe to generate the code you want is a great idea, but more generally, you can access the property name via reflection using an approach similar to the accepted answer # workarounds for nameof() operator in C#: typesafe databinding.
var textValue = entity.FormattedValues["new_myoptionset"];
// becomes
var textValue = entity.FormattedValues
[
// renamed the class from Nameof to NameOf
NameOf(Xrm.MyEntity).Property(x => x.new_MyOptionSet).ToLower()
];
The latest version of the CRM Early Bound Generator includes a Fields struct that that contains the field names. This allows accessing the FormattedValues to be as simple as this:
var textValue = entity.FormattedValues[MyEntity.Fields.new_MyOptionSet];
You could create a new property via an interface for the CrmSvcUtil, but that's a lot of work for a fairly simple call, and I don't think it justifies creating additional properties.
I am using the alarm clock code that I found and trying to customize it.
But I get this error : "com.android.internal.R cannot be resolved to a variable "
for code:
getListView().setItemsCanFocus(true);
// Grab the content view so we can modify it.
FrameLayout content = (FrameLayout) getWindow().getDecorView()
.findViewById(com.android.internal.R.id.content);
I am not sure what this piece of code is doing ( so that I could change it)
Can you please help me resolve this by some alternative piece of code?
The solution is simple.
Just replace: com.android.internal.R.id.content with android.R.id.content
You can directly use R.id.content, you need to have a view by that name in layout.
In your gen->R.java file there should be an int named content which corresponds to a view which should be declared in your res->layout folder. This int would be created automatically by Android.
I'm using EntityFramework 4.3 beta version and its Data Migration facility. I wrote following code for generating a custom Migration and apply it to the DB.
MigrationScaffolder ms=new MigrationScaffolder(configuration);
ScaffoldedMigration scaffoldedMigration= ms.Scaffold("Migration");
DbMigrator dbMigrator = new DbMigrator(configuration);
dbMigrator.Update(scaffoldedMigration.MigrationId);
Scaffolding function worked fine and generated a Migration correctly.
But an exception comes up and says
"The specified target migration '201201230637551_Migration' does not
exist. Ensure that target migration refers to an existing migration
id."
Does this happen since still this is a beta version? Can someone help me to solve this.
Thank you.
This is not because you were using a beta version. MigrationScaffolder class is only to generate a configuration class. That generated file is not being added to the solution automatically. If we want to pass it into DbMigrator.Update() method, we should add the generated file into the solution first. Then we should make an instance of that class, and pass it into the update() method like this.
{
DbMigrationsConfiguration myConfiguration=new MyConfiguration();
DbMigrator dbMigrator = new DbMigrator(configuration);
dbMigrator.Update(myConfiguration);
}
Here MyConfiguration is the generated class.
Additionally, you do not need to apply migrations into your project this way. Instead you can use:
{
DbMigrationsConfiguration myConfiguration=new DbMigrationsConfiguration(){
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
}
DbMigrator dbMigrator = new DbMigrator(configuration);
dbMigrator.Update(myConfiguration);
}