Dialog RunBase custom lookup: Alt + Down key combination doesn't work - dialog

MS Dynamics AX 4.0
I have a class with a dialog that extends RunBase, a dialogField of Range type and a custom lookup for it. It works as planned but one thing upsets me.
Normal lookup opens on Alt + Down key combination, but it doesn't work in my dialog. I assume this is because "Range" EDT is not related to any TableField.
But I have my own lookup, can I force it somehow to drop down on Alt + Down?
Here is my dialog method:
protected Object dialog(DialogRunBase dialog, boolean forceOnClient)
{
Object ret;
;
ret = super(dialog, forceOnClient);
dialogFld = new DialogField(ret, typeid(Range), 100);
dialogFld.init(ret);
dialogFld.lookupButton(FormLookupButton::Always);
dialogFld.fieldControl().replaceOnLookup(false);
return ret;
}
Here is my lookup, as you can see, it's based on ItemId EDT:
protected void Fld100_1_Lookup()
{
TableLookup_RU sysTableLookup = new TableLookup_RU();
Query query = new Query();
FormRun lookupForm;
QueryBuildDataSource qbds = query.addDataSource(tablenum(InventTable));
;
sysTableLookup.parmTableId(tablenum(InventTable));
sysTableLookup.parmCallingControl(dialogFld.fieldControl());
sysTableLookup.addLookupfield(fieldnum(InventTable, ItemId));
sysTableLookup.addLookupfield(fieldnum(InventTable, ItemName));
findOrCreateRange_W(qbds, fieldnum(InventTable, ItemType), SysQuery::valueNot(ItemType::Service));
sysTableLookup.parmQuery(query);
lookupForm = sysTableLookup.formRun();
dialogFld.fieldControl().performFormLookup(lookupForm);
}
And dialogPostRun:
public void dialogPostRun(DialogRunbase dialog)
{
;
dialog.formRun().controlMethodOverload(true);
dialog.formRun().controlMethodOverloadObject(this);
super(dialog);
}
This problem is not that critical, but it bothers me. If someone could help, I'd be really grateful.
P.S.: I could use ItemId typeId, but I need to append many items, and ItemId is only 20 chars long..

I've discovered that I don't have to use Range typeid for the dialogField. dialogField.limitText(int) works just fine, it overrides the length of EDT. So I changed dialog method like this:
protected Object dialog(DialogRunBase dialog, boolean forceOnClient)
{
Object ret;
;
ret = super(dialog, forceOnClient);
dialogFld = new DialogField(ret, typeid(ItemId), 100); //if typeId doesn't have relations Alt + Down doesn't work
dialogFld.init(ret);
dialogFld.label("#SYS72708");
dialogFld.lookupButton(FormLookupButton::Always);
dialogFld.limitText(200);
dialogFld.fieldControl().replaceOnLookup(false);
return ret;
}

Create a new extended data type ItemIdRange, extend from Range.
Be sure to set the relation on the new type to relate to InventTable.ItemId to get automatic lookup.
Also the form control must have property ReplaceOnLookup set to no, to allow the user to add more criteria. For a DialogRunbase field this may be done this way:
FormStringControl fsc = dialogField.control();
fsc.replaceOnLookup(false);
The code posted in the question is then not needed.

Related

Unity Vuforia Google VR - Can't make onPointerEnter to GameObject change material for itself

I have two 3d buttons in my scene and when I gaze into any of the buttons it will invoke OnPointerEnter callback and saving the object the pointer gazed to.
Upon pressing Fire1 on the Gamepad I apply materials taken from Resources folder.
My problem started when I gazed into the second button, and pressing Fire1 button will awkwardly changed both buttons at the same time.
This is the script I attached to both of the buttons
using UnityEngine;
using UnityEngine.EventSystems;
using Vuforia;
using System.Collections;
public class TriggerMethods : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
Material _mat;
GameObject targetObject;
Renderer rend;
int i = 0;
// Update is called once per frame
void Update () {
if (Input.GetButtonDown("Fire1"))
TukarMat();
}
public void OnPointerEnter(PointerEventData eventData)
{
targetObject = ExecuteEvents.GetEventHandler<IPointerEnterHandler>(eventData.pointerEnter);
}
public void OnPointerExit(PointerEventData eventData)
{
targetObject = null;
}
public void TukarMat()
{
Debug.Log("Value i = " + i);
if (i == 0)
{
ApplyTexture(i);
i++;
}
else if (i == 1)
{
ApplyTexture(i);
i++;
}
else if (i == 2)
{
ApplyTexture(i);
i = 0;
}
}
void ApplyTexture(int i)
{
rend = targetObject.GetComponent<Renderer>();
rend.enabled = true;
switch (i)
{
case 0:
_mat = Resources.Load("Balut", typeof(Material)) as Material;
rend.sharedMaterial = _mat;
break;
case 1:
_mat = Resources.Load("Khasiat", typeof(Material)) as Material;
rend.sharedMaterial = _mat;
break;
case 2:
_mat = Resources.Load("Alma", typeof(Material)) as Material;
rend.sharedMaterial = _mat;
break;
default:
break;
}
}
I sensed some logic error and tried making another class to only manage object the pointer gazed to but I was getting more confused.
Hope getting some helps
Thank you
TukarMat() is beeing called on both buttons when you press Fire1. If targetObject is really becoming null this should give an error on first button since it's trying to get component from a null object. Else, it'll change both as you said. Make sure OnPointerExit is beeing called.
Also, it seems you are changing the shared material.
The documentation suggests:
Modifying sharedMaterial will change the appearance of all objects using this material, and change material settings that are stored in the project too.
It is not recommended to modify materials returned by sharedMaterial. If you want to modify the material of a renderer use material instead.
So, try changing the material property instead of sharedMaterial since it'll change the material for that object only.

Change String length or decimal precision of field attribute dynamically

I'm trying to use setup data from one table to allow me to format fields on the fly / dynamically. I know I can change field names and visibility based on the PXUIFieldAttribute class, but changing the precision or string length is a bit trickier, obviously. From the research I've done, I've come up with the following example code that seems like it should work - but I get the error:
"Unable to cast object of type 'PX.Data.PXUIFieldAttribute' to type 'PX.Data.PXDBDecimalAttribute'.
I don't see why this is occurring...
protected virtual void xTACOpenSourceDetail_RowSelected(PXCache sender, PXRowSelectedEventArgs e)
{
var osd = (PXCache)sender;
foreach (PXDBDecimalAttribute attribute in this.Caches<xTACOpenSourceDetail>().GetAttributes("Number1"))
{
PXDBDecimalAttribute someAttribute = attribute as PXDBDecimalAttribute;
if (someAttribute != null)
{
someAttribute.DBProperties._precision = 4;
}
}
}
I just tried the below code in sales order screen and it seems working!
var props = typeof(SOOrder).GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(PXDecimalAttribute)));
foreach (System.Reflection.PropertyInfo item in props)
{
PXDecimalAttribute.SetPrecision(this.Base.Caches[typeof(SOOrder)], item.Name, 1);
}
You might need to change this to match your DAC.

How to use ABPeoplePickerNavigationController in MonoTouch to pick a specific email address or phone number of a contact?

I have been using the ABPeoplePickerNavigationController in a project, written in MonoTouch, to pick a specific email address or phone number of a contact.
The code set a delegate, and in the delegate I implemented the ShouldContinue method, and retrieved the contact using the Handle property of all contacts. Unfortunately, it looks like something changed, or that I used undocumented features, or that I was simply lucky, because now when I'm in the process of updating the app for iPhone 5, the code no longer works.
Edit: Ok, my initial thoughts was that this was caused by changes in MonoTouch, since there has been quite a few updates since I last worked on this app. However, I now removed it from my device and downloaded the version I have on the app store, and it crashes in the same manner, null reference exception.
This means it is an iOS upgrade that made my code non-functional.
The goal of my code:
Pick a person's specific email address, not just the person, but navigating into the details of the person, and selecting a specific email address or telephone number.
The below code deals with phone numbers only, the email code looks 95% similar.
Here is the code that constructs the picker:
var picker = new ABPeoplePickerNavigationController();
picker.Init();
picker.DisplayedProperties.Clear();
picker.DisplayedProperties.Add(ABPersonProperty.FirstName);
picker.DisplayedProperties.Add(ABPersonProperty.Phone);
var del = new PhonePickerDelegate();
picker.Delegate = del;
Here is the delegate class:
private class PhonePickerDelegate : ABPeoplePickerNavigationControllerDelegate
{
public override bool ShouldContinue(ABPeoplePickerNavigationController peoplePicker, IntPtr selectedPerson, int propertyId, int identifier)
{
peoplePicker.DismissModalViewControllerAnimated(true);
// THE NEXT LINE IS THE ONE THAT NO LONGER WORKS
var contact = peoplePicker.AddressBook.SingleOrDefault(s => s.Handle == selectedPerson) as ABPerson;
using (var phones = contact.GetPhones())
{
int index = phones.GetIndexForIdentifier(identifier);
var phone = phones.GetValues()[index];
var name = (contact.FirstName + " " + contact.MiddleName).Trim() + " " + contact.LastName;
Selected(name + ": " + phone);
}
return false;
}
public override void Cancelled(ABPeoplePickerNavigationController peoplePicker)
{
peoplePicker.DismissModalViewControllerAnimated(true);
}
}
Unfortunately this code no longer finds the correct contact, as none of the contacts has a Handle value that corresponds to the selectedPerson IntPtr value.
My questions are these:
How can I fix the above code?
Can I fix the above code?
Is there some other class/method/delegate/event or whatnot I should be using instead?
You could do something like the following:
Note that AppDelegate.navigation would be your current NavigationController
using MonoTouch.AddressBookUI;
using MonoTouch.AddressBook;
ABPeoplePickerNavigationController _contactController = new ABPeoplePickerNavigationController ();
AppDelegate.navigation.PresentViewController (_contactController, true, null);
_contactController.Cancelled += delegate {
AppDelegate.navigation.DismissViewController (true, null);
return;
};
_contactController.SelectPerson += delegate(object sender, ABPeoplePickerSelectPersonEventArgs e) {
_importedContact = e.Person;
AppDelegate.navigation.DismissViewController (true, delegate {
// What to do when you dismiss the picker here.
});
};
e.Person is only going to give you the whole contact. You would want to do something like:
e.Person.GetEmails().FirstOrDefault
Hope this helps

Is there a way to override the handler called when a user clicks a checkbox in a CListCtrl? (MFC)

I am trying to disable the user's ability to alter the state of a checkbox in a List Control. I am currently changing the state pragmatically. I already handle the LVN_ITEMCHANGED message, and trying to alter the state there isn't an option due to the layout of the rest of the program. I have also tried doing a HitTest when the user clicks in the List Control and simply resetting the checkbox there but that isn't giving me the exact results I am looking for.
Is there a specific message sent or a function I can override when the user clicks the checkbox itself? I would just like to override the handler or catch the message so that it doesn't go anywhere.
Solution:
I ended up removing the LVS_EX_CHECKBOXES flag and created my own implementation. That way the there is only one way to change the icons. Reading the link from the previous question gave me an idea to set a "busy" flag, otherwise I would get stack overflow errors.
// In my dialog class
m_CListCtrl.SetImageList(&m_ImgList, LVSIL_SMALL); // Custom checkboxes (only two images)
// ...
void CMyDialog::OnLvnItemchangedList(NMHDR *pNMHDR, LRESULT *pResult)
{
if(busy) { return; }
// ....
}
// When calling the SetCheck function:
busy = TRUE; // Avoid stack overflow errors
m_CListCtrl.SetCheck(index, fCheck);
busy = FALSE;
// I derived a class from CListCtrl and did an override on the get/set check:
class CCustomListCtrl : public CListCtrl
{
BOOL CCustomListCtrl::SetCheck(int nItem, BOOL fCheck)
{
TCHAR szBuf[1024];
DWORD ccBuf(1024);
LVITEM lvi;
lvi.iItem = nItem;
lvi.iSubItem = 0;
lvi.mask = LVIF_TEXT | LVIF_IMAGE;
lvi.pszText = szBuf;
lvi.cchTextMax = ccBuf;
GetItem(&lvi);
lvi.iImage = (int)fCheck;
SetItem(&lvi);
return TRUE;
}
// Just need to determine which image is set in the list control for the item
BOOL CCustomListCtrl::GetCheck(int nItem)
{
LVITEM lvi;
lvi.iItem = nItem;
lvi.iSubItem = 0;
lvi.mask = LVIF_IMAGE;
GetItem(&lvi);
return (BOOL)(lvi.iImage);
}
}
This is not as elegant as I had hoped, but it works flawlessly.

Deselect text in a textbox

I have a windows form that sets the text property in a textbox to that of a string variable. When the form is ran, it has all of the text in the textbox selected. I need to try and figure out how to keep that from happening. I tried the
DeslectAll()
method on the textbox but that doesn't seem to work. I also tried
txtBox.SelectNextControl(txtCostSummary, true, false, true, true);
but I kind of was guessing on what the paramters needed to be set to, tweaking them doesn't seem to make a difference. To really understand what I'm doing I'll make it a little more clear on how this all is happening.
public Form1()
{
Apple a = new Apple();
a.IwantThisText = "Item 1: " + 50.00 + "\r\n";
txtBox.Text = a.IwantThisText;
}
Class Apple
{
private string iWantThisText;
public string IwantThisText
{
get { return iWantThisText; }
set { iWantThisText += value; } // Appends what was there before
}
}
Everything works fine except the part where it has printed the information in the textbox but all the text in the textbox is selected, which isn't what I thought would happen, nor is it what I want to happen.
Thanks for any ideas!
Try this:
txtBox.Select(0, 0);
I know it's an old question, but I found that this works too:
txtBox.SelectionLength = 0;
This might be preferable to #SteveCav's Select(0,0) as it doesn't move the selection start point.
Try this:
//remove focus from control.
Apple a = new Apple();
a.IwantThisText = "Item 1: " + 50.00 + "\r\n";
txtBox.Text = a.IwantThisText;
// Add this
txtBox.TabStop = false;

Resources