How to access child controls inside inherited class? - class

Here is what I'm doing, I have a large amount of reports, rather than copy and pasting the repeated code, I have the following..
public class ReportPage : System.Web.UI.Page
{
// Code
}
My report Pages have
public class MyReportPage : ReportPage
{
}
Problem I'm having is, I want to be able to access a control inside MyReportPage within ReportPage, for instance, I want all pages grid to have a specific property.
Inside ReportPage I tried
protected void Page_PreRender(object s, EventArgs e)
{
var obj = this.FindControl("reportGridName");
}
But unable to find the control, went through all the controls to see if I could it in, no luck..
Any ideas how to get the grid access on the inherit?

Page page = (Page)HttpContext.Current.Handler;
var obj = page.FindControl("reportGridName");
Does that work? I'm having the exact same problem and stumbled upon this link

Related

Fuelphp - route index with parameters

Using Fuelphp, I'd like to be able to use a URL system similar to here on StackOverflow to get to specific pages.
Desired behavior:
-stackoverflow.com/questions -> page with many questions
-stackoverflow.com/questions/1982 ->page with specific question
Here's my controller:
class Controllers_Images extends Controller_Template
{
public function action_index($id=null)
{
if($id)
{
//Use Model_Image to find specific image
//Create appropriate view
}
else
{
//Use Model_Image to find many images
//Create appropriate view
}
}
}
I can access the "generic" page with mysite.com/images/ - this is routed to the action_index function. I can access a "specific" page with mysite.com/images/index/1. What I'd like to do is be able to skip index in this case too, so that mysite.com/images/1 works. Right now I'm getting 404. How do I set up routing for this?
After poking around a bit more, I came up with a solution that works fine:
class Controllers_Images extends Controller_Template
{
public function action_index()
{
//Use Model_Image to find many images
//Create appropriate view
}
public function get_id($id)
{
//Use Model_Image to find specific image
//Create appropriate view
}
}
In routes.php:
return array(
'images/(:num)'=>'images/id/$1',
//other routing stuff...
);
With this setup, the url "mysite.com/images/1" now appropriately displays the selected image as if "mysite.com/images/id/1" was used instead. Not a huge deal, but it is a nicer interface, which is important!

How to bind view model to a UserControl in MVVMCROSS?

I am using the excellent Mvvmcross and Ninja Coder for Mvvmcross for building a cross platform app. For my windows store app I have created a view and a view model using Ninja coder. I have also created a UserControl which will be referenced in the view. Hence I need to bind the same viewmodel to the User control also. I have been trying to set the Data context of the user control to the singleton instance of viewmodel. I have set the data context of the user control like below.
public sealed partial class SearchResultsGridViewControl : UserControl
{
private SearchresultsViewModel _viewModel;
public SearchResultsGridViewControl()
{
this.InitializeComponent();
_viewModel = Mvx.IocConstruct<SearchresultsViewModel>();
this.DataContext = _viewModel;
}
}
But when I refer this User Control in my main view, it throws an error in XAML saying "Object Reference not set to an instance of an object. Cannot create an instance of SearchResultsGridViewControl".
This is my viewmodel:
public class SearchresultsViewModel : BaseViewModel
{
private ISearchResultsService _searchResultsService;
public SearchresultsViewModel(ISearchResultsService searchResultsService)
{
_searchResultsService = searchResultsService;
var items = _searchResultsService.DisplaySearchResults();
SchoolDetails = new ObservableCollection<School>(items);
}
private ObservableCollection<School> _schoolDetails;
public ObservableCollection<School> SchoolDetails
{
get { return _schoolDetails; }
set
{
_schoolDetails = value;
RaisePropertyChanged(() => SchoolDetails);
}
}
public ICommand RefineCommand
{
get
{
refineCommand = refineCommand ?? new MvxCommand(FilterSearchResultsBasedOnRefine);
return refineCommand;
}
}
public void FilterSearchResultsBasedOnRefine()
{
SchoolDetails = new ObservableCollection<School>(_searchResultsService.FilterSchoolsBasedOnRefine(MidDayMeals, PlayGround, DigitalClassroom, DayBoarding, TransportationFacility));
}
}
The grid view in my usercontrol is getting populated when it loads for the first time. But when RefineCommand is called to update the collection from the main view, the grid view in usercontrol is not getting updated. And I am guessing its because of that error earlier in setting the data context of the user control to view model. Please let me know what could be going wrong. I have been banging my head about it for days.
I've been using MVVMCross with Windows Store fairly recently. Without looking back at my code, I'm pretty sure that the Datacontext will inherit from it's parent unless overridden.
So as long as the MvxPage that you have presented has a viewmodel, any user control that you add to it, either in XAML or in code-behind, should share the same data context. If you are looking at doing some MVVMCross data-binding from the User Control, you should probably make sure your User Control implements IMvxStoreView, and ensure that the ViewModel property is set to the value of DataContext.
Hope that help.
Cheers,
Tristan
I think your first problem "Object Reference not set to an instance of an object" is a design time only issue - because you are trying to set the viewmodel using Mvx. at design time. You can workaround this issue if you want to by using design time viewmodels and possibly also by using one of the design time helpers (see https://github.com/MvvmCross/MvvmCross/blob/v3.1/CrossCore/Cirrious.CrossCore.Wpf/Platform/MvxDesignTimeHelper.cs).
I've no idea what your second problem is "The grid view in my usercontrol is getting populated when it loads for the first time. But when RefineCommand is called to update the collection from the main view, the grid view in usercontrol is not getting updated" - this sounds like an issue either in your xaml or in the results returned from FilterSearchResultsBasedOnRefine. From the current level of detail, I can't see what it is. My "gut feeling" is that the problem won't be MvvmCross specific - it'll just be a general Mvvm/data-binding issue.

MvvmCross: Android custom webview urls handlers

My Android application had some complex text with hyperlinks embedded inside. The easiest way for me to handle this was to just use an embedded WebView and detect hyperlink clicks to perform custom commands. I am trying to do this the MvvmCross way. Is there a binding available for WebView.SetBackgroundColor or WebView.LoadData? Once I get my custom html inside and the user clicks on hyperlinks, I have used WebView.SetWebViewClient to install my own client which can detect hyperlink clicks and perform custom actions. Any way to turn all of that into proper MvxCommand usage?
Is there a binding available for WebView.SetBackgroundColor
For View color binding see the sample: https://github.com/slodge/MvvmCross-Tutorials/tree/master/ValueConversion
or WebView.LoadData?
See Dynamic Binding UIWebView in MVVMCross
I have used WebView.SetWebViewClient to install my own client which can detect hyperlink clicks and perform custom actions. Any way to turn all of that into proper MvxCommand usage?
It's not clear to me what your question is. Maybe try coding something first and then coming back with some sample code for the problem - eg come back with a specific question about a specific ViewModel so that others can try to answer at a code level instead of at this more general level. Perhaps also try asking one question at a time and asking with a deeper level of detail - How to ask may help you get better results - see https://stackoverflow.com/questions/how-to-ask
I created a custom WebView by inheriting and added Command properties. I then added a custom WebViewClient to detect certain URL's and to call the corresponding command that was bound. Is this a good way to accomplish this?
public class AboutWebView : WebView
{
public IMvxCommand AboutCommand { get; set; }
public IMvxCommand LicenseCommand { get; set; }
public IMvxCommand PrivacyCommand { get; set; }
public AboutWebView (Context ctx,IAttributeSet aset) : base(ctx,aset)
{
SetWebViewClient (new AboutWebViewClient(this));
}
private class AboutWebViewClient : WebViewClient
{
private AboutWebView _parent = null;
public AboutWebViewClient(AboutWebView parent)
{
_parent = parent;
}
public override bool ShouldOverrideUrlLoading (WebView view, string url)
{
if (url.StartsWith ("about://"))
_parent.AboutCommand.Execute ();
else if (url.Equals (App.LICENSE_URL))
_parent.LicenseCommand.Execute ();
else
_parent.PrivacyCommand.Execute ();
return(true);
}
}
}

calling a child page component from parent page component in wicket

I have a problem which I tried to explained in the Image.I hope that will help all to understand what I need.
My Base Page is like this (menuNavPanel is the tree panel):
<div class="colContainer">
<div class="leftColumn" >
<div wicket:id="menuNavPanel"></div>
</div>
<div class="rightColumn">
<wicket:child/>
</div>
</div>
And Ny BIA Page which is a child of Base Page is like this:
<wicket:extend>
<div wicket:id="bodyPanel"></div>
</wicket:extend>
in my Tree Panel, when I click on a node the code is this:
#Override
protected void onNodeLinkClicked(AjaxRequestTarget target, TreeNode node) {
super.onNodeLinkClicked(target, node);
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)node;
Unit unitObject =(Unit) treeNode.getUserObject();
// I want to call bodyPanel fo child page passing the unitObject param
}
Now, How can I call bodyPanel fo child page passing the unitObject param from the tree panel of the parent page?
Am I been able to express my problem? Hoping to get some help :)
Instead of doing the override method, upgrade to Wicket 1.5 and utilize the new event bus to communicate between your components. You can create a custom, type-safe, event that is specific to your component's use case: for example "ItemAddedToShoppingCart" or "GlobalThermoNuclearWarStarted".
The linked article in the 1.5 migration guide provides enough information on how to set up things.
I'm not sure I understand que question correctly. Your BasePage defines a left column with the TreePanel and lets subclasses expand themselves inside the right column div. You usually put a BodyPanel inside BasePages's subclasses. And now you want to invoke a BodyPanel's method on some event on the TreePanel.
You could do it with an overridable method on BasePage, which would be called in TreePanel through getPage(). Your child pages would override that method, and its implementation would call the BodyPanel they're holding.
public class BasePage ... {
// Hook
public void treePanelSelected(Object someObject) { }
...
}
public class ChildPage extends BasePage ... {
BodyPanel bodyPanel;
#Override
public void treePanelSelected(Object someObject) {
bodyPanel.selectionChanged/(someObject);
}
...
}
public class TreePanel ... {
...
#Override
protected void onNodeLinkClicked(AjaxRequestTarget target, TreeNode node) {
super.onNodeLinkClicked(target, node);
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)node;
Unit unitObject =(Unit) treeNode.getUserObject();
((BasePage)getPage()).treePanelSelected(unitObject);
}
}
From my ignorance on your specific needs and details of implementation, I don't see why is subclassing the BasePage necessary. You could add the BodyPanel right there in the BasePage and control it from the same class.
Thanks all, After reviewing all the nice options I finally opted out for the event bus way defined by martijn. What I did is I have created an event payload and connected the panels for the talking. I also needed to pass the selected Id / entity to the receiving panel.
Is there a way to set a compound property model of the receiving panel according to the model of the tree element so that I don't need to do the model manually ?
I did like this for the time being:
public class TreeNodeClickUpdate {
private final AjaxRequestTarget target;
private final long selectedId;
/**
* Constructor
*
* #param target
* #param selectedId
*/
public TreeNodeClickUpdate(AjaxRequestTarget target, long selectedId)
{
this.target = target;
this.selectedId = selectedId;
}
/** #return ajax request target */
public AjaxRequestTarget getTarget()
{
return target;
}
public long getSelectedId() {
return selectedId;
}
}
On the sender side I've done like this:
send(getPage(), Broadcast.BREADTH,
new TreeNodeClickUpdate(target, unitObject.getId()));
And on the receiving end I got it like this:
#Override
public void onEvent(IEvent<?> event) {
super.onEvent(event);
if (event.getPayload() instanceof TreeNodeClickUpdate)
{
TreeNodeClickUpdate update = (TreeNodeClickUpdate)event.getPayload();
setSelectedId(update.getSelectedId()); //sets to id field of panel
update.getTarget().add(this);
}
}
and for just as an example in my receiving panel, to get the value I have created a label like this:
label = new Label("label",new PropertyModel<BiaHomePanel>(this,"selectedId"));
Later, in reality I want to get information from the entity and show in form. Is there a nice way to pass models in a better way or I should pass as a parameter in event payload.
There are two ways to do this. One is cleaner, but requires more code. The other is quick and dirty.
Method 1: (Good)
Since your parent page is being extended, you can provide an abstract method in the parent like
protected abstract WebMarkupContainer getBodyPanel();
that is implemented in your child page and returns the appropriate panel. Then, you can call that method from the panel in your parent page. This is similar to the overrideable method suggested by the other user.
Method 2: (Bad)
The Wicket Component Hierarchy is shared between the parent and child pages. So, if you make sure that your bodyPanel has a unique wicketId and is added directly to the root of the page, you can probably just call
get("bodyPanelId");
and it will return the proper panel.
When I was facing the problem, I thought of two ways to solve this (pre 1.5):
a) implement a variation of the observer pattern to notify other component of events like outlined here: Realising complex cross-component ajax actions in wicket - The observer way
b) using wicket visitors to traverse the component tree doing the same.
I decided to go for variant a) but this introduces coupling from your component to your page-implementation which leads to problems when testing panels on their own. So maybe b) might be the better idea but since my application is running quite smoothly with a) implemented and the next big step will be switching over to 1.5 and the event bus, I haven't yet tried b).

GWT - Code Splitting - How can GWT know which data load first time?

Im curios about this. I have for example this code :
button_article.addClickListener(new ClickListener(){
public void onClick(Widget w) {
GWT.runAsync(new RunAsyncCallback() {
public void onFailure(Throwable reason) {
// somethings
}
public void onSuccess() {
content.clear();
content.designArticles();
}
});
}
});
public final void designArticles() {
this.add(new ProfileArticles(this.rpcService, this));
}
I see that until i click on button_article, the elements on ProfileArticles() (that is a FlowPanel) arent loaded when i start the application. So, how can GWT know that element on that class shouldnt loaded when the application start? It check each methods under GWT.runAsync() and their correspondents Class?
I also see that when i leave that "context" they arent released (in fact, if i change context and i return there, when i click again on that method it doesnt call the server. So it use the previous loaded code). Is it right? :)
Cheers
The GWT compiler analyzes the flow of your program to figure out what chunks it can load later. If you want to visually understand what it's done, check out http://code.google.com/webtoolkit/doc/latest/DevGuideCompileReport.html .
Once code is loaded, most of it can be cached, so even if the user navigates off the page and then back to yours, the code will not need to be reloaded.