I have a C# program that launches a dialog inside a DialogHost:
Dialogs.ViewModels.WriteProgramToDatabaseDialogViewModel vm = new Dialogs.ViewModels.WriteProgramToDatabaseDialogViewModel();
var view = new Views.WriteProgramToDatabaseDialogView
{
DataContext = vm
};
var result = await DialogHost.Show(view, "RootDialog");
DialogHost is a feature of ButchersBoy's MaterialDesign framework. DialogHost
The WriteProgramToDatabaseDialogViewModel is simply a class that derives from Caliburn Micro's "Screen".
Now, Caliburn Micro has spoiled me and I am used to being able to declare controls and use the x:Name property in the XAML to bind them. This does not work at all in the dialog's ViewModel and I am failing to understand why.
Fortunately, I can still setup databinding for controls by explicitly setting it:
<TextBlock Grid.Row="1" Text="{Binding MyTextProp}"/>
In order to bind buttons to methods in the ViewModel, I can explicitly bind the Click event:
<Button cal:Message.Attach="[Event Click] = [Action RunMethodInVM]"/>
My question is: can with anyone with experience of both Caliburn Micro and Butchers Boy's Materialize explain why the x:Name abstraction doesn't work inside a DialogHost?
Related
We're using Prism with UWP, and have a UserControl which we want to display several times in a Grid (each instance relating to a connected user).
If the UserControl were a Page, I know of course that the code can/should go in associated ViewModel. What's the equivalent for the UserControl? I obviously want to keep my code DRY, and call the same code for each UserControl instance.
My research is pointing me towards a Dependency Property, but I haven't found a clear example of how I should implement it.
Note that the UserControl needs to display data and also implement Buttons with associated Commands on the ViewModel.
Create a separate view model
You could create a view model specifically for the user control. The DataContext of the user control would be set to an instance of this view model. You can expose commands and data related to each user in the view model and bind to them in the user control, just like you would if it were a page.
This scenario works best if the user control can function independently of the page it is in. If you need the user control VM to communicate to the page VM, then you'll need to facilitate this somehow between the VMs (maybe the user control VM can take a reference to the page VM as a dependency upon construction).
Expose command properties in the user control
Another way is to create dependency properties for each command you want to expose in the user control, which can then be bound to in the page's XAML.
<UserControl>
<Grid>
<Button Content="Delete" Command="{x:Bind DeleteCommand}"/>
</Grid>
</UserControl>
public sealed partial class MyUserControl : UserControl
{
public ICommand DeleteCommand
{
get { return (ICommand)GetValue(DeleteCommandProperty); }
set { SetValue(DeleteCommandProperty, value); }
}
public static readonly DependencyProperty DeleteCommandProperty =
DependencyProperty.Register("DeleteCommand", typeof(ICommand), typeof(MyUserControl), new PropertyMetadata(null));
}
Now you can bind to DeleteCommand on the user control.
Typically I use some combination of both of these methods when I use user controls.
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 am trying to develope a component for my company wich should have an integrated dialog. Creating the component was easy until i hit the point with the Dialog. I want to use the com.ibm.xsp.extlib.component.dialog.UIDialog for my component because it has some nice features wich i want to use so creating my own dialog with a ClientSideDojo is not an option.
Normaly when adding a component to another i use component.getChildren().add(MyNewComp),but when i try this Code:
public class myComponentWithADialog extends UIComponentBase implements FacesComponent {
//...other Code...
public void buildContents(FacesContext context, FacesComponentBuilder builder)
throws FacesException {
UIDialog dialog = new UIDialog();
TypedUtil.getChildren(container).add(dialog);
dialog.setStyleClass("dlgUserPref");
dialog.setTitle("titelxyz");
dialog.setId("TagDialog");
UIPanelEx panel = new UIPanelEx();
panel.setTagName("div");
panel.setStyle("border:2px solid red;");
panel.setStyleClass("lotusList lotusTags lotusRelatedTags");
dialog.getChildren().add(panel);
this.getChildren.add(dialog);
}
//....
}
My Panel does not display inside the dialog when calling XSP.openDialog('dialogClientId') in my browser the dialog is shown but empty.
I already tried several other methods like dialog.getPopupContent.getChildren().add() but then i get the error: javax.faces.component.UIPanel incompatible with com.ibm.xsp.extlib.component.dialog.UIDialog$PopupContent.
Also i tried to find a solution on google but i only found a entry at openNTF from someone with the same problem but also without any solution.
Note: I also tried to 'inject' some content to a standard <xe:dialog> and to a <px:panel> inside the <xe:dialog> via a button with SSJS like keithstric does in his blog. Code:
var dialog:com.ibm.xsp.extlib.component.dialog.UIDialog =
getComponent('extlibdialog');
if(dialog.getChildren().size() > 0) {
dialog.getChildren().clear();
}
var TextField:com.ibm.xsp.component.xp.XspOutputText = new com.ibm.xsp.component.xp.XspOutputText();
TextField.setTitle("test");
TextField.setId("testTextField");
TextField.setValue("<p>This is the new Content</p>");
dialog.getChildren().add(TextField);
This code works fine for a standard <xp:panel> outside a dialog but not on the dialog itself or a panel inside it.
The dialogue is not pre - rendered when the page is loaded, but when you actually call for it in XSP.openDialog(...)
So you need to get your code run in that event (mobile now, can't check if it is exposed).
Plan B: do use a Dojo dialogue that is backed by a rest control, so you can transport whatever data you need back and forth.
A word of caution: popup dialogs are a UI concept transplanted from desktop apps. They are alien to Web apps and mostly not working in mobile. Consider and Inline form instead (or a wizard)
I have made a Container compound by a TextArea and a CheckBox. In my app, I create so many of this "Containers" and add to each TextArea inside of them an ActionListener (implemented by the class). Something like this:
for(int i = 0 ; i<20;i++){
MyContainer c = new MyContainer();
TextArea t = c.getTextArea();
t.addActionListener(this);
}
I want the TextArea to catch the event and if it is pressed put the CheckBox checked or unchecked. It works fine in non-touch devices and simulators but in the touch devices or emulators, the TextArea doesn't catch the event. I tried to put the TextAreaas the lead component of the Container but it doesn't works because Container doesn't have an addActionListener method.
If I understand the question correctly you are trying to create a compound component assembled from multiple different components to act like a single component. In LWUIT/Codename One this is called a Lead Component, the attached post is mostly about the resource editor but the concepts apply to manual coding as well.
Just set the "checkbox" as your lead and everything should work.
You can code this manually by deriving and overriding but you will there are small edge cases like the change of style states (focused/pressed state etc.)
It is better that you derive the TextArea class for the getTextArea() method. Then in this class implement the pointerReleased method : code the action performed in the normal way in it.
I have used DependencyProperty to pass value from textbox at silverlight page to external silverlight user control located in same page and that works fine.
But the problem is I could not bind the Textbox in page in reverse way. i.e. when i need to have changes in parent page when its usercontrol's textbox text is changed.
The XAML:
<TextBox x:Name="TextDataCollectionAccounts" Width="200" Height="25" VerticalAlignment="Top"></TextBox>
<Local:CalControl x:Name="RCal" DateRange="{Binding ElementName=TextDataCollectionAccounts, Path=Text, Mode=TwoWay}" Visibility="Collapsed"/>
How to bind "TextDataCollectionAccounts"(in silverlight page) with Textbox of "Local:CalControl"?
Basically never try to bind to the inner workings of a user control. Treat it like it was a third-party control and expose properties and events.
Expose the Text property of the TextBox as a Text dependency property on your usercontrol.
Catch the change event of the TextBox and raise a property change event for the new Text dependency property.
Then you can simply bind to your new Text property on your user control.
If you need a specific example, just ask, but it sounds like you are almost there and know your DPs.