Routed Event Args with ButtonBase - wpf-controls

I am currently working on a program with a team of members and they don't know how to solve this either. I created a set of specialty user controls "ImageButton". I am using that for the menu section of the program. The menu itself is another user control.
They are currently using ButtonBase.Click to access the buttons, but it doesn't work with my new ImageButtons.
The ButtonBase.Click leads to an event called "MainMenu_Click".
private void MainMenu_Click(object sender, RoutedEventArgs e)
{
Button _menuButtonClicked = (Button)e.OriginalSource;
this.ShowMainPage((MainMenuCommands)_menuButtonClicked.Tag);
}
I have already tried parsing them as ImageButtons but it has not worked. So I need a solution that is similar to ButtonBase.Click but for my ImageButtons.
Edit:
There are 3 files I am working with:
MainWindow.xaml (and its cs)
MainMenu.xaml (and its cs)
ImageButton.xaml (and its cs)
MainMenu has several ImageButtons on it. MainMenu is used on MainWindow. One of the properties to set is ButtonBase.Click. But I need that to be setup for ImageButtons not System.Windows.Controls.Button.

You would need to make your ImageButton derive from ButtonBase (or Button) -- then you'll get all of ButtonBase such as its events like Click. It's actually quite simple to do this. I have a RibbonButton that's like an image button which derives from Button as a custom control. You write the template in Generic.xaml to set the look, then add any other properties and code.

Related

Create a generic popup panel

I have added a Global Button with the following code.
public override void Initialize()
{
if (!String.IsNullOrEmpty(Base.PrimaryView))
{
Type primaryViewItemType = Base.Views[Base.PrimaryView].Cache.GetItemType();
PXAction action = PXNamedAction.AddAction(Base, primaryViewItemType, "SubmitTicket", "Submit Ticket", TestClick);
}
}
public IEnumerable TestClick(PXAdapter adapter)
{
throw new PXException("Button clicked from graph" + Base.GetType().Name);
}
And it renders the button like this in each of the pages.
Now, I would like to display a popup panel, on button's click. I know I can create a popup panel on screen section. But, is there some way that I can have a general popup panel created in one place and can be displayed on each of the pages on the button's click?
Thank you.
As #HB_ACUMATICA mentioned there is no good easy way.
Providing another alternative to his post, you can create a graph and use it as a reusable popup by calling:
throw new PXPopupRedirectException(graph, string.Empty, true)
One thing I ran into was a sizing issue on the popup...
Changing the height/width when calling another graph as an in-page popup using PXPopupRedirectException
If you do copy and paste the PXSmartPanel you can create re-usable business logic by implementing the reusable business logic pattern found in this help as a starting point:
Reusing Business Logic
If I understand correctly you want to share the same PXSmartPanel control in different pages without having to copy/paste it in every screen.
In Acumatica Framework this is achieve by custom container controls like 'PXUploadDialog' which derives functionality from other controls like 'PXSmartPanel'. This is the control that is used when you attach files in all screen.
Unfortunately there seems to be no documentation on how to achieve this.
The closest I found is this SO question which is essentially unanswered:
Create custom User Control for Acumatica
Considering this, you may want to copy/paste the same smart panel in all screen.
To ease copying you can use the 'Edit ASPX' feature, make sure you backup the project before.
Edit ASPX to get to the code:
Copy paste your smart panel in the page and click 'GENERATE CUSTOMIZATION SCRIPT' to package the changes in the project:

How do I play a sound in response to a custom action or button in Acumatica?

We have a need to play a sound file on grid cell, for this we have used the below control <audio> similar to how the default Acumatica used in some of the screens for Barcode scanning, etc. We did the same, but when we register the script and control code is changing to <PXControl> and the methods for Play etc., are not not accessible. This is happening only when we try to insert this audio control inside a customization package. On the ASPX all the functionality works fine.
Before Generating Script in the package
<audio id="audiobeep" preload="auto" src="http://www.soundjay.com/button/beep-07.wav" style="visibility: hidden" />
After Generating Script in the package
<px:Control runat="server" ID="audiobeep" />
As “audio” tag is converting into “px: control” tag, it doesn’t support properties like as Preload, Src, Style.
Can you please guide us on this approach?
When using the Aspx Editor with the "Generate Customization Script" button, the only supported way to embed arbitrary HTML tags like <audio> is to use the PXLiteral control. Here's an example of how you would use the PXLiteral control if typing directly into the Aspx Editor:
<px:PXLiteral runat="server" Text="<h1>Test!</h1>" />
Once the script has been generated, it becomes possible to edit the properties of the control from the layout editor.
For this specific scenario, I would suggest a slightly different approach, involving only the use of JavaScript code connected to the PXDataSource control. The first step is creating a PXAction in your graph that will be invoked when you click on your button:
public PXAction<Customer> test;
[PXUIField(DisplayName = "Test", MapEnableRights = PXCacheRights.Update, MapViewRights = PXCacheRights.Select, Enabled = false)]
[PXButton(ImageKey = PX.Web.UI.Sprite.Main.Process)]
public virtual IEnumerable Test(PXAdapter adapter)
{
//TODO: Do something useful
return adapter.Get();
}
For simplicity, let's assume that you're ok having the button in the main screen toolbar - but you could also map it to a PXButton control somewhere on your page.
Then, using the layout editor, we're going to add a JavaScript control by dragging it to the form.
After the JavaScript control has been added, head over to the properties section and set the script. The script needs to be set as a single-line, but for readability here's a nicely formatted version of the script we're going to use:
function commandResult(ds, context)
{
if (context.command == 'Test') // Test is the name of the PXAction we created earlier
{
var audio = new Audio('../../Sounds/Ding.wav');
audio.play();
}
}
Note: The Ding.wav file is shipped with Acumatica, but you are free to use a sound from another URL, or ship one with your customization. If using an external URL, make sure to use the right protocol, HTTP/HTTPS.
The last step is hooking the data source to your JavaScript function. To do that, click on the DataSource section of the layout editor, open the Client Events group from the property editor, and set the CommandPerformed event to commandResult which is the name of the JavaScript function we created.
After publishing, you'll see the Test button in the toolbar of the form. If you click on it, you'll hear a nice ding!
The sound will be played unconditionally, no matter what happens in your PXAction delegate. If you wanted to play the sound under specific conditions only, one way to achieve that would be to read the content of a field on the screen that is set by your delegate, similar to what is done in the IN305000 page:
var description = px_alls["edDescriptionPnl"];
if (description != null && description.getValue() != null)
{
var audio = new Audio('../../Sounds/Ding.wav');
audio.play();
}

I have added an OnPaint() function to my dialog class but its not getting called after dlg.DoModal()

Can anyone please help me understand how to override OnPaint() for a dialog class derived from CDialog.
Here is the code:
ColorImageDlg *pDlg = NULL;
pDlg = new ColorImageDlg;
pDlg->DoModal();
delete pDlg;
I'm overriding OnInitDialog() and it's getting called.
But while overriding OnPaint() it is not getting called.
Can any one please help me fixing it?
First of all what is the point of creating the instance of the dialog on heap? You can simply do:
ColorImageDlg dlg;
dlg.DoModal();
You need to modify your message map like this:
BEGIN_MESSAGE_MAP(ColorImageDlg, CDialog)
ON_WM_PAINT()
END_MESSAGE_MAP()
Use VS Class Wizard to avoid problems like that.
If you can't use the ClassWizard then there is another way. Here is a resource about it:
(VS2015 version) https://msdn.microsoft.com/en-us/library/dey7ke4c.aspx
(VS2008 version) https://msdn.microsoft.com/en-us/library/dey7ke4c(v=vs.90).aspx)
But basically, once you have defined the dialog resource and attached it to a new class, make sure the Class View tab is selected:
Next, make sure your dialog class is selected in the class view:
Then, click on the Messages icon of the Properties panel:
Scroll down the list of messages and locate WM_PAINT. Then click the dropdown arrow and select the option to add it:
As you can see, it has inserted all the needed code:
Hope this helps.

Hide Controls At Design-Time [duplicate]

I need to handle multiple panels, containing variuous data masks. Each panel shall be visible using a TreeView control.
At this time, I handle the panels visibility manually, by making the selected one visible and bring it on top.
Actually this is not much confortable, especially in the UI designer, since when I add a brand new panel I have to resize every panel and then design it...
A good solution would be using a TabControl, and each panel is contained in a TabPage. But I cannot find any way to hide the TabControl buttons, since I already have a TreeView for selecting items.
Another solution would be an ipotethic "StackPanelControl", where the Panels are arranged using a stack, but I couldn't find it anywhere.
What's the best solution to handle this kind of UI?
You need a wee bit of Win32 API magic. The tab control sends the TCM_ADJUSTRECT message to allow the app to adjust the tab size. Add a new class to your project and paste the code shown below. Compile. Drop the new control from the top of the toolbox onto your form.
You'll get the tabs at design time so you can easily switch between pages. The tabs are hidden at runtime, use the SelectedIndex or SelectedTab property to switch between "views".
using System;
using System.Windows.Forms;
class StackPanel : TabControl {
protected override void WndProc(ref Message m) {
// Hide tabs by trapping the TCM_ADJUSTRECT message
if (m.Msg == 0x1328 && !DesignMode) m.Result = (IntPtr)1;
else base.WndProc(ref m);
}
}
A good solution would be using a TabControl, and each panel is contained in a TabPage.
But I cannot find any way to hide the TabControl buttons, since I already have a
TreeView for selecting items.
For the above,
You need to set the following properties of TabControl.
tabControl.Multiline = true;
tabControl.Appearance = TabAppearance.Buttons;
tabControl.ItemSize = new System.Drawing.Size(0, 1);
tabControl.SizeMode = TabSizeMode.Fixed;
tabControl.TabStop = false;

How to control application from WebBrowser Control?

I've googled it, but came out empty. And the worst thing is that I know it is possible.
Anyway, I'm developing an application that uses the WebBrowser control to display information regarding an object (like Outlook does with the Rules and Alerts dialog box).
My question is how do I do for the click on a, say, hyperlink in the WebBrowser execute some function within the Windows Form?
For instance, say I have a link like this and when I click it I want the application to display an specific form, like the Outlook does when you click on hyperlinks like People and Distribution List
This looks useful: How to: Implement Two-Way Communication Between DHTML Code and Client Application Code
ChrisW's answer will work, but there's another way if you're just relying on hyperlinks.
In Comicster, I have links in my WebBrowser control like this:
New Collection
And then in the WebBrowser's Navigating event, I have some code to check if the user has tried to navigate to an "action:" link, and intercept it:
private void webBrowser1_Navigating(object sender,
WebBrowserNavigatingEventArgs e)
{
if (e.Url.Scheme == "action")
{
e.Cancel = true;
string actionName = e.Url.LocalPath;
// do stuff when actionName == "FileNew" etc
}
}
With a little bit of code you can even parse the URL parameters and "pass them through" to your host application's action, so I can do things like:
Edit this issue
... which will open a properties dialog for the issue with ID 1.

Resources