How To Add Monotouch Dialog to FlyoutNaviagtionController - xamarin.ios

I'm a noob to monotouch and can't manage to add table views to flyoutnavigation controller. Does anyone have an example?
** update
My setup is a bit complicated and after much hacking managed to get the static table cells displayed on my storyboard with the below config.
tab bar controller
|
-tab 1
|
-tab 2 - nav controller
|
uiview controller A - flyout nav A --> uiview controller A1...A3
|
uiview controller B - flyout nav B --> tableview controller B1 (static cells)
I've cast the tableview controllers as uiview controllers on the flyout navs' setup thus allowing the tableviewcontroller to be displayed correctly and navigated to main uiview controllers via sergues. For example in the flyouts setup:
NavigationRoot = new RootElement ("FlyoutNavigationB") {
new Section ("Pages") {
new StringElement ("A Table View with static cells")
}
},
ViewControllers = new [] {
TableViewControllerB1 as UIViewController,
},
This hack seems to work but cleaner solutions are warmly invited (as I'm only 2weeks dev experience with monotouch) and feel a little saddened that I have uiview controllers sitting unattached on the storyboard without ability to do sergues via the flyout nav. It almost behaves like old school xib development.
Anyway I'm experimenting with tying this upto monotouch dialog now but not yet sure how. Comments most welcome to aid my learning :P
* update
Ok I think I got it working by creating a subclassed dialogviewcontroller. Then passing this subclass instance into the ViewControllers array in flyoutnavigationcontroller like so:
public partial class MyDvcController : DialogViewController
{
public MyDvcController (UINavigationController nav): base (UITableViewStyle.Grouped, null)
{
navigation = nav;
Root = new RootElement ("Demos"){
new Section ("Element API"){
new StringElement ("iPhone Settings Sample", DemoElementApi),
}
};
}
}
In my calling flyoutnav controller:
// Supply view controllers corresponding to menu items:
ViewControllers = new [] {
new UIViewController { View = new UILabel { Text = "Address txt" }, Title = "Address" },
new MyDvcController(NavigationController) as UIViewController
}
My wish list is almost complete...now how to add custom upickerviews with lovely transparent input accessory views wired to inputviews so they show automatically from calling monotouch dialog elements...hmmmm...another quest awaits...

Are you trying to push a second list over inside the flyout? I couldn't get it to work either.
I got it to work by modifying the source and redoing how the selection list is setup--but those changes are on my machine at work. I'll try to push those when I have a chance.

Related

Make Two Views Share Click Feedback in Constraint Layout

I have this situation where I have a constraint layout. Within it lies two views. An ImageView and a TextView. When either of these Views is clicked, I want both to produce a feedback (text color change for textview and drawable tint in imageview) but I can't seem to think of a way to do these unless I put them inside another viewgroup.
Can someone show me how this could be done in constraint Layout? thank you.
Take a look at performClick().
performClick
boolean performClick ()
Call this view's OnClickListener, if it is defined. Performs all normal actions associated with clicking: reporting accessibility event, playing a sound, etc.
The idea is that when one view is clicked, your code will call performClick() on the other view. You will have to make sure that you inhibit any duplication of actions if the two views do the same function.
Other than doing this in code, I don't know of a way using just XML. There is the concept of a Group in ConstraintLayout but that just a way to control the visibility of the members of the group and does not extend to other properties.
I would use another enclosing view group unless you have a requirement not to. I just seems easier.
Use Group concept in ConstraintLayout refer: https://developer.android.com/reference/android/support/constraint/Group ,https://riggaroo.co.za/constraintlayout-guidelines-barriers-chains-groups/ ,
in java
Group group = findViewById(R.id.group);
int refIds[] = group.getReferencedIds();
for (int id : refIds) {
findViewById(id).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// your code here.
}
});
}
Kotlin:
fun Group.setAllOnClickListener(listener: View.OnClickListener?) {
referencedIds.forEach { id ->
rootView.findViewById<View>(id).setOnClickListener(listener)
}
}
Then call the function on the group:
group.setAllOnClickListener(View.OnClickListener {
// your code here.
})

Dynamically added menu (PXAction + MenuAutoOpen + AddMenuAction) gets hidden in some screens, but not others

I am trying to dynamically add a menu and related actions through a graph extension. The code I have written works in some screens but not in others. I can see the menu appear during post-back but it gets hidden right away: http://recordit.co/T5KSEz7QJv
I have spent a few hours investigating the problem and here's what I found so far:
If I don't add my action to a menu, it works in every cases. The issue is only when using AddMenuAction. I see that there's some logic inside PXAction to show/hide the menu based on visibility of the items inside the menu, but I couldn't figure the problem out.
If the menu itself is directly declared in the graph extension (using public PXAction... and attributes), it works as expected. It is not an option in my case because I am trying to create a generic mechanism that will allow me to add actions to any graph type.
The two following graph extensions highlight this problem - the first one is for Sales Orders entry, and the other for Business Account maintenance. They are identical, except for the graph type parameter:
//This extension works fine, button displays as expected
public class TestButtonsSO : PXGraphExtension<SOOrderEntry>
{
public override void Initialize()
{
base.Initialize();
Type primaryViewItemType = Base.Views[Base.PrimaryView].Cache.GetItemType();
var myMenu = PXNamedAction.AddAction(Base, primaryViewItemType, "MyMenu", "My Menu",
a => a.Get(),
new PXEventSubscriberAttribute[] { new PXButtonAttribute() { MenuAutoOpen = true } });
var action = PXNamedAction.AddAction(Base, primaryViewItemType, "MyMenu$Test", "Test",
a => throw new PXException("Clicked!"),
new PXEventSubscriberAttribute[] { new PXButtonAttribute() { } });
myMenu.AddMenuAction(action);
}
}
//The menu will appear during post-back but gets hidden right away
public class TestButtonsBAccount: PXGraphExtension<BusinessAccountMaint>
{
public override void Initialize()
{
base.Initialize();
Type primaryViewItemType = Base.Views[Base.PrimaryView].Cache.GetItemType();
var myMenu = PXNamedAction.AddAction(Base, primaryViewItemType, "MyMenu", "My Menu",
a => a.Get(),
new PXEventSubscriberAttribute[] { new PXButtonAttribute() { MenuAutoOpen = true } });
var action = PXNamedAction.AddAction(Base, primaryViewItemType, "MyMenu$Test", "Test",
a => throw new PXException("Clicked!"),
new PXEventSubscriberAttribute[] { new PXButtonAttribute() { } });
myMenu.AddMenuAction(action);
}
}
Upon the investigation, this issue seems to be caused by PXGridWithPreview corrupting ToolBarItemCollection in the DataSource. Your approach above will perfectly work on all Acumatica screens, which do not contain a PXGridWithPreview control. For screens already utilizing PXGridWithPreview, we'll have to wait until a fix is realised by Acumatica Engineering Team (will keep this item on my radar and post an update once the fix is available)

How to create layout elements in Orchard 1.9

Can someone please guide me on how to create layout elements in Orchard 1.9. I couldn't find any resource online.
In general, creating a new layout element is similar to creating a new part. There is a driver and a few views involved in the process. To the point - you need to implement as follows:
An element class.. Class that inherits from Element, which contains all the element data. A model, so to speak.
A driver. Class that inherits from ElementDriver<TElement>, where TElement is the type you created above. Each element has it's own driver that handles displaying admin editor (and the postback) and frontend display views.
Shapes. All shapes should be placed under /Views/Elements/ folder, by convention.
Display shape. Named after your element, ie. MyElement.cshtml. This one renders your element on frontend.
Design display shape.. Named after your element, with .Design suffix, ie. MyElement.Design.cshtml. This one renders your element inside the layout editor.
Editor shape.. This one should be put in /Views/EditorTemplates/ folder instead. Default naming convention is Elements.MyElement.cshtml. It renders the editor shown when you drop a new element on layout editor canvas.
With all above done, your new element should appear in the list of elements on the right side of the layout editor, ready to use.
If you want to do some more complex elements, please check the existing implementations. Layouts module has a very decent architecture so you should get up to speed pretty quickly. Just keep in mind the necessary steps I wrote above.
To create a custom layout element first create a class that inherits from Element. Element is found in the Orchard.Layouts namespace so you need to add a reference. To follow Orchard standards put this file in a folder called Elements.
public class MyElement : Element
{
public override string Category
{
get { return "Content"; }
}
public string MyCustomProperty
{
get { return this.Retrieve(x => x.MyCustomProperty); }
set { this.Store(x => x.MyCustomProperty, value); }
}
}
Next, create a driver class in a folder called Drivers. This class inherits from ElementDriver<TElement> and likely you will want to override the OnBuildEditor and OnDisplaying methods. OnBuildEditor is used for handling creating our editors shape and updating our database when the editor is saved. OnDisplaying is used when we need to do things when displaying our element. Oftentimes, you will want to add properties to the shape which can be done with context.ElementShape.MyAdditionalProperty = "My Value";
public class MyElementDriver : ElementDriver<MyElement>
{
protected override EditorResult OnBuildEditor(MyElement element, ElementEditorContext context)
{
var viewModel = new MyElementEditorViewModel
{
MyCustomProperty = element.MyCustomProperty
};
var editor = context.ShapeFactory.EditorTemplate(TemplateName: "Elements.MyElement", Model: viewModel);
if (context.Updater != null)
{
context.Updater.TryUpdateModel(viewModel, context.Prefix, null, null);
element.MyCustomProperty = viewModel.MyCustomProperty;
}
return Editor(context, editor);
}
protected override void OnDisplaying(Reddit element, ElementDisplayContext context)
{
context.ElementShape.MyAdditionalProperty = "My Value";
}
}
We then just need our views. Our editor view goes into Views/EditorTemplates. The file name needs to be what we set the template name of the editor shape. In our case the view name will be Elements.MyElement.cshtml.
#model MyNameSpace.ViewModels.MyElementEditorViewModel
<fieldset>
<div>
#Html.LabelFor(m => m.MyCustomProperty, T("My Custom Property"))
#Html.TextBoxFor(m => m.MyCustomProperty, new { #class = "text medium" })
</div>
</fieldset>
Finally, we just need a view for our frontend. This view goes into the following folder Views/Elements. The name of the view file is the same as our element class name. For this example the file would be called MyElement.cshtml.
#using MyNameSpace.Elements
#using MyNameSpace.Models
#{
var element = (MyElement)Model.Element;
}
<h1>#element.MyCustomProperty</h1>
You will then have a new element that you can drag into your layout with the layout editor.
For more details on creating an element from start to finish check out my blog post on creating a Reddit element.

EXT.Net - Dynamic UserControlLoader with Property

I need a solution to the below scenario. I'm developing an application in ASP.Net with the help of EXT.Net Controls.
In my scenario, I'm creating dynamic tabs (EXT.Net) and loading an User Control dynamically with UserControlLoader component.
How can I pass a parameter to the UserControl dynamically? Below is my sample code.
[DirectMethod]
public void AddNewTab()
{
getTitle gt = new getTitle();
Ext.Net.Panel panel = new Ext.Net.Panel
{
Title = gt.Title(),
Closable = false,
Layout = "Fit",
Items = {
new UserControlLoader{
Path="ElementChooser.ascx"
}
}
};
TabPanel1.Add(panel);
panel.Render();
TabPanel1.SetLastTabAsActive();
}
Your help is highly appreciated.
It is a bit unclear what "pass a parameter to a User Control" means, but I think you need to handle the UserControlLoader's OnUserControlAdded and OnComponentAdded events.
The first one fires when a user control is added to a UserControlLoader.
The second one fires for each top level Ext.NET component from a user control.
These events helps to configure a user control and its components as needed.
Here is an example with the OnComponentAdded example.

Orchard CMS: Do I have to add a new layer for each page when the specific content for each page is spread in different columns?

Lets say I want a different main image for each page, situated above the page title. Also, I need to place page specific images in the left bar, and page specific text in the right bar. In the right and left bars, I also want layer specific content.
I can't see how I can achieve this without creating a layer for each and every page in the site, but then I end up with a glut of layers that only serve one page which seems too complex.
What am I missing?
If there is a way of doing this using Content parts, it would be great if you can point me at tutorials, blogs, videos to help get my head round the issue.
NOTE:
Sitefinity does this sort of thing well, but I find Orchard much simpler for creating module, as well as the fact that it is MVC which I find much easier.
Orchard is free, I understand (and appreciate) that. Just hoping that as the product evolves this kind of thing will be easier?
In other words, I'm hoping for the best of all worlds...
There is a feature in the works for 1.5 to make that easier, but in the meantime, you can already get this to work quite easily with just a little bit of code. You should first add the fields that you need to your content type. Then, you are going to send them to top-level layout zones using placement. Out of the box, placement only targets local content zones, but this is what we can work around with a bit of code by Pete Hurst, a.k.a. randompete. Here's the code:
ZoneProxyBehavior.cs:
=====================
using System;
using System.Collections.Generic;
using System.Linq;
using ClaySharp;
using ClaySharp.Behaviors;
using Orchard.Environment.Extensions;
namespace Downplay.Origami.ZoneProxy.Shapes {
[OrchardFeature("Downplay.Origami.ZoneProxy")]
public class ZoneProxyBehavior : ClayBehavior {
public IDictionary<string, Func<dynamic>> Proxies { get; set; }
public ZoneProxyBehavior(IDictionary<string, Func<dynamic>> proxies) {
Proxies = proxies;
}
public override object GetMember(Func<object> proceed, object self, string name) {
if (name == "Zones") {
return ClayActivator.CreateInstance(new IClayBehavior[] {
new InterfaceProxyBehavior(),
new ZonesProxyBehavior(()=>proceed(), Proxies, self)
});
}
// Otherwise proceed to other behaviours, including the original ZoneHoldingBehavior
return proceed();
}
public class ZonesProxyBehavior : ClayBehavior {
private readonly Func<dynamic> _zonesActivator;
private readonly IDictionary<string, Func<dynamic>> _proxies;
private object _parent;
public ZonesProxyBehavior(Func<dynamic> zonesActivator, IDictionary<string, Func<dynamic>> proxies, object self) {
_zonesActivator = zonesActivator;
_proxies = proxies;
_parent = self;
}
public override object GetIndex(Func<object> proceed, object self, IEnumerable<object> keys) {
var keyList = keys.ToList();
var count = keyList.Count();
if (count == 1) {
// Here's the new bit
var key = System.Convert.ToString(keyList.Single());
// Check for the proxy symbol
if (key.Contains("#")) {
// Find the proxy!
var split = key.Split('#');
// Access the proxy shape
return _proxies[split[0]]()
// Find the right zone on it
.Zones[split[1]];
}
// Otherwise, defer to the ZonesBehavior activator, which we made available
// This will always return a ZoneOnDemandBehavior for the local shape
return _zonesActivator()[key];
}
return proceed();
}
public override object GetMember(Func<object> proceed, object self, string name) {
// This is rarely called (shape.Zones.ZoneName - normally you'd just use shape.ZoneName)
// But we can handle it easily also by deference to the ZonesBehavior activator
return _zonesActivator()[name];
}
}
}
}
And:
ZoneShapes.cs:
==============
using System;
using System.Collections.Generic;
using Orchard.DisplayManagement.Descriptors;
using Orchard;
using Orchard.Environment.Extensions;
namespace Downplay.Origami.ZoneProxy.Shapes {
[OrchardFeature("Downplay.Origami.ZoneProxy")]
public class ZoneShapes : IShapeTableProvider {
private readonly IWorkContextAccessor _workContextAccessor;
public ZoneShapes(IWorkContextAccessor workContextAccessor) {
_workContextAccessor = workContextAccessor;
}
public void Discover(ShapeTableBuilder builder) {
builder.Describe("Content")
.OnCreating(creating => creating.Behaviors.Add(
new ZoneProxyBehavior(
new Dictionary<string, Func<dynamic>> { { "Layout", () => _workContextAccessor.GetContext().Layout } })));
}
}
}
With this, you will be able to address top-level layout zones using Layout# in front of the zone name you want to address, for example Layout#BeforeContent:1.
ADDENDUM:
I have used Bertrand Le Roy's code (make that Pete Hurst's code) and created a module with it, then added 3 content parts that are all copies of the bodypart in Core/Common.
In the same module I have created a ContentType and added my three custom ContentParts to it, plus autoroute and bodypart and tags, etc, everything to make it just like the Orchard Pages ContentType, only with more Parts, each with their own shape.
I have called my ContentType a View.
So you can now create pages for your site using Views. You then use the ZoneProxy to shunt the custom ContentPart shapes (Parts_MainImage, Parts_RightContent, Parts_LeftContent) into whatever Zones I need them in. And job done.
Not quite Sitefinity, but as Bill would say, Good enough.
The reason you have to create your own ContentParts that copy BodyPart instead of just using a TextField, is that all TextFields have the same Shape, so if you use ZoneProxy to place them, they all end up in the same Zone. Ie, you build the custom ContentParts JUST so that you get the Shapes. Cos it is the shapes that you place with the ZoneProxy code.
Once I have tested this, I will upload it as a module onto the Orchard Gallery. It will be called Wingspan.Views.
I am away on holiday until 12th June 2012, so don't expect it before the end of the month.
But essentially, with Pete Hurst's code, that is how I have solved my problem.
EDIT:
I could have got the same results by just creating the three content parts (LeftContent, RightContent, MainImage, etc), or whatever content parts are needed, and then adding them to the Page content type.
That way, you only add what is needed.
However, there is some advantage in having a standard ContentType that can be just used out of the box.
Using placement (Placement.info file) you could use the MainImage content part for a footer, for example. Ie, the names should probably be part 1, part 2, etc.
None of this would be necessary if there was a way of giving the shape produced by the TextField a custom name. That way, you could add as may TextFields as you liked, and then place them using the ZoneProxy code. I'm not sure if this would be possible.

Resources