I am making a proof of concept WPF application with Prism 4 and Unity, but I run into some basic problems.
In our solution we have the following projects:
-AppName.Desktop
-AppName.Modules.ModuleA
-AppName.Modules.ModuleB
Having followed some tutorials, explored some examples and searched the internet, I wasn't able to find a suitable answer to a very rudimentary question; how can I switch between two views in different DLL's.
The first view (ModuleAView) is loaded in the Initialize method of ModuleA:
public void Initialize()
{
regionManager.RegisterViewWithRegion("MainRegion", typeof(Views.ModuleAView));
}
When I click in ModuleAView (or on a button in ModuleAView) I want to switch to ModuleBView.
public bool SomeEventInModuleAView(SomeEventParams e)
{
Uri viewNav = new Uri("ModuleBView", UriKind.Absolute);
regionManager.RequestNavigate(RegionNames.MainRegion, viewNav);
}
Obviously this won't work, since ModuleA doesn't know where to find ModuleBView. I have read about changing the URI with pack/application/component etc, but I can't seem to make it work.
I was thinking something like this:
Uri("pack://application:,,,/AppName.Modules.ModuleB;component/Views/ModuleBView.xaml", UriKind.Absolute);
Since loading modules from different assemblies is one of the purposes of Prism, I think it's strange that there aren't any examples in the Prism download to show how this works.
I have found the answer. I totally forgot to register the second view.
Check the solution over here: http://compositewpf.codeplex.com/discussions/402860#post940396
Related
I'd like to create an attached property in my C++/Cx WinRT project. When I do so, the XAML compiler complains that I'm using an unknown property.
I'm declaring my attached property in a cpp file as such:
/*--------------------------------------------------------------------
Forward Declarations
--------------------------------------------------------------------*/
namespace
{
void
StateChanged(
DependencyObject^ target,
DependencyPropertyChangedEventArgs^ args);
}
/*--------------------------------------------------------------------
DependancyProperty setup for the view model
--------------------------------------------------------------------*/
namespace
{
DependencyProperty^ _stateProperty =
DependencyProperty::RegisterAttached(
"State",
TypeName(Platform::String::typeid),
TypeName(VisualStateManagerBindingHelper::typeid),
ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(&StateChanged)));
}
namespace
{
void
StateChanged(
DependencyObject^ target,
DependencyPropertyChangedEventArgs^ args)
{
if (args->NewValue != nullptr)
{
VisualStateManager::GoToState(safe_cast<Control^>(target), safe_cast<String^>(args->NewValue), true);
}
}
}
In my XAML file, I'm attempting to use the attached property as such:
<UserControl
xmlns:local="using:MyCustomNamespace"
...
<Grid Grid.Column="1" local:VisualStateManagerBindingHelper.State="{Binding Path=SomeViewModelProperty, Mode=TwoWay}">
...
When I compile, I'm faced with this error:
XamlCompiler error WMC0010: Unknown attachable member 'VisualStateManagerBindingHelper.State' on element 'Grid'
It appears to me as if the XAML compiler is supposed to get a hint somewhere that this attached property is allowed, but I don't know how to give it that hint. This article on the same subject suggests that the DependancyProperty should be public. I'm not entirely sure how to do that in C++.
My ultimate goal is to bind a visual state group's state to some view model property. The method to do this is outlined in the accepted answer in this question. Unfortunately, the code provided there is C# and I can't seem to translate it over to C++ properly.
Finally, I noticed the SuspensionManager that comes with Visual Studio's new project templates defines an attached property almost exactly like I do, but they don't show any examples of it in use. This makes me feel like I'm on track, but missing some small piece of the puzzle.
I found a site that answered my question! As I suspected, you need to have your class defined in a very specific way for the XAML preprocessor to know about your attached property. All of the requirements along with a code sample are available here.
Does any one know a way to find out unused views in project ? with Resharper or without it.
any idea which is easier than writing down all the views and go through all controllers and check manually is appreciated :)
Thanks
With ReSharper you can right-click a Razor view and Find Usages, but you'd have to go through manually and repeat for all views (unless you can hook into ReSharper's API and automate it).
The problem with views of course is that they're late-bound based on a convention defined in the view engine, in the case of the default RazorViewEngine it looks for a corresponding view in ~/Views/{Controller}/{Action} and ~/Views/Shared/{Action}. So it's difficult to tell at design or compile time which views, partials and templates are never used.
You might approch it from the opposite angle: find which views are being used. Then diff this list against all views in the project, evaluate the results (manually and with ReSharper Find Usages) and confirm they're really not being used before finally removing them.
To find the views being used you could customise the RazorViewEngine to log every time it loads a view with CreateView and FindPartialView, e.g.
public class LoggingRazorViewEngine : RazorViewEngine
{
protected override IView CreateView(
ControllerContext controllerContext,
string viewPath,
string masterPath)
{
LogManager.GetLogger("").Debug(viewPath);
return base.CreateView(controllerContext, viewPath, masterPath);
}
}
Configure it in global.asax.cs
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new LoggingRazorViewEngine());
Then extract a list of logged unique view paths to compare against your project's views. Bit of effort involved, but possibly worth if if you've got lots of unused views cluttering up the project.
You could rename one of the suspicious views and compile... if some controller is using it you will get errors :)
Don't know of any "built in" feature to look for unused views.
Right now, I'm working on my first WP7 app and have run into some questions, which I haven't been able to answer despite reading what I could find online. Please consider an app that has a main page, a parameters page and a results page. In the parameters page, the user can enter or update numbers in various textboxes. Hitting the back button takes the user back to the main page, where there is a button called "Calculate". Hitting that button should take the data, perform a calculation with it and take the user to the results page presenting a grid with the results.
In a file called Calculator.cs I have a class called Calculator inside a folder called Models. I also have my MainViewModel.cs, ParametersViewModel.cs, and ResultsViewModel.cs files inside the ViewModels folder and the corresponding MainPage.xaml, along with Parameters.xaml and Results.xaml inside a folder called Views. I'm assuming that all the data will be manipulated within the instance of the Calculator class and then a results set will be returned and directed to Results.xaml. I'm just at a loss as to where to instantiate the Calculator class, pass it data, then retrieve the results. I'm also somewhat puzzled how I will trigger the automatic navigation to the Results page when the calculation is done.
Any help with this would be greatly appreciated.
UPDATE: Passing a complex object to a page while navigating in a WP7 Silverlight application has some more info on the same subject. I can go into App.xaml.cs and add something like this:
public class Foobar
{
public string barfoo = "hah!";
}
public static Foobar myfoob = new Foobar();
Then access it from a ViewModel page, e.g. AboutViewModel.cs, like this:
public AboutViewModel()
{
string goo = App.myfoob.barfoo;
}
But at this point I'm still uncertain what unforseen effects that might have. I'm going to tackle serialization/tombstoning at this point to see what happens with either this approach or by using the same DataContext across pages. Otherwise, one of the posters in the link above mentioned serializing the params and passing them between pages. My concern there would be whether or not there is a character limit as with HTTP GET. Seems there is: URI Limits in Silverlight
There are of course lots of possible designs - and lots of them are correct in different ways!
Here's one I might use:
The Calculate button press should trigger the Navigate to the Results page
On navigate to, the Results page should show some animation (maybe just a progress bar)
On navigate to, the Results page should create a new ResultsViewModel, passing in the MainViewModel as parameters
the constructor (or some init method) of the ResultsViewModel should spark up a thread to do the calculation
when this calculation is complete, then the relevant properties of the ResultsViewModel will get set
at which point the databinding on the Results page will clear the animation and show the results
Other solutions are definitely available - will be interested to read what other people suggest and prefer.
As an aside, one thing to watch out for on your Results page is tombstoning - could be an interesting challenge!
I'm currently putting together a multi-tenancy web app using MVC 3. At least 30 different Web sites will share a common codebase, and while also sharing similar under-the-hood functionality, they are need to look significantly different. As a consequence I'm using the URL to internally separate out clients, and an overridden Razor view engine (at least in terms of finding the view) to automatically select either a customised view for a given action, or the default view.
To help 'compartmentalise' a complex page, any particular view will make use of several partials, usually rendered as self-contained actions, so that generally a custom view or partial view will only have small HTML differences, helping to minimise any code specific to a client's site.
I hope you followed that background!
So one HTML page might be made up of lots of little smatterings of HTML partial views, which could come from specific folders for the client, or a general-purpose version. I'm hoping to make it easier for our designer to make minor changes to a page by easily seeing where in the folder structure the bit of HTML he wants to change are.
My proposal then is that each partial will be 'bracketed' with HTML comments such as:
{ Content of partial }
Obviously I could put these in manually, but that's just asking for trouble, for typos, for copied and then modified client versions not being updated with the correct URL. It should be possible to get this from some context and inject it, I think.
At the same time, I need to be able to not do this for certain Actions. Eg, a partial might be generating text inside a textarea, say, so the comments wouldn't be appropriate there. On the whole I'm happy to put these comments in unless I specify that it's not appropriate.
For me this suggests an ActionFilter on an Action, which I can apply site wide and then turn off for certain Actions. I'd hope that one of the overridable events would let me ascertain this path, but I can't seem to find anywhere it's stored. Furthermore, OnResultExecuting seems to fire before the Partial has been selected, and OnResultExecuted seems to have already written out the contents of the Partial, so I can't insert the starting comment here. I also can't find any reference to the path of the selected partial.
Just for completeness, it's my intention that this attribute would only write these comments when compiled in Debug mode.
So, does anyone know how I might be able to get the path to the selected View without any kind of hack between FindPartialView and the Attribute? Is my Attribute method the best choice or is there an easier way to do this? Perhaps something's built in already!
Many thanks for your help.
Well, I've never forgotten about wanting this, and always hoped I'd solve it one day, and thankfully I have.
I've overridden the default WebViewPage (I use the Razor engine), and in particular ExecutePageHierarchy to inject the comments:
public abstract class PaladinWebViewPage : PaladinWebViewPage<dynamic>
{
}
public abstract class PaladinWebViewPage<TModel> : WebViewPage<TModel>
{
public bool DisplaySourceCodeComments
{
get { return ((bool?) ViewBag.__DisplaySourceCodeComments) ?? false; }
set { ViewBag.__DisplaySourceCodeComments = value; }
}
public override void ExecutePageHierarchy()
{
base.ExecutePageHierarchy();
// Filters can be used to set and clear this value so we can decide when to show this comment
if (!DisplaySourceCodeComments) return;
var sw = Output as StringWriter;
if (sw == null) return;
var sb = sw.GetStringBuilder();
sb.Insert(0, string.Format("<!-- Start of {0} -->", VirtualPath));
sb.AppendFormat("<!-- End of {0} -->", VirtualPath);
}
VirtualPath tells us the exact file used to build the HTML, so we can inject the filename before and after. This isn't doing anything at the moment, since the default is to not show comments (the "?? false" in DisplaySourceCodeComments).
Also to use this view page you need to edit Views/Web.config and change the pageBaseType to this type.
I want to selectively turn these comments on and off so I've created an ActionFilter:
public class DisplaySourceCodeCommentsAttribute : ActionFilterAttribute
{
private readonly bool _displaceSourceCodeComments;
public DisplaySourceCodeCommentsAttribute(bool displaceSourceCodeComments)
{
_displaceSourceCodeComments = displaceSourceCodeComments;
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext);
var viewResult = filterContext.Result as ViewResultBase;
if (viewResult == null) return;
viewResult.ViewBag.__DisplaySourceCodeComments = _displaceSourceCodeComments;
}
}
I'm slightly unhappy that I've had to use the ViewBag here and also separately in the view page override, as they aren't tightly linked, but I can't find a way for the filter to directly interact with the view page, so this is something of a necessary fudge. It does have the benefit that displaying source code for a view or partial also automatically displays it for any child partials until you turn it off again, since the ViewBag is passed down the chain.
With this in place, any action can turn on the source code comments with
[DisplaySourceCodeComments(true)]
or, obviously turn it off again with false
The Attribute checks that the context result is a ViewResultBase, which means just Views and Partials, so Json or Content or redirects aren't affected, which is very handy too.
Finally, I make this action filter a global when running in debug mode so that every view, and partial has the source comment included, by adding the following line to global.asax.cs:
[#]if DEBUG
// When in debug mode include HTML comments showing where a view or partial has come from
GlobalFilters.Filters.Add(new DisplaySourceCodeCommentsAttribute(true));
[#]endif
I'm really happy I've finally got it sorted so I hope this is useful for someone else.
This should be quite a common problem, but I couldn't find anything helpful on the topic.
We are developing an application with Eclipse RCP. The application shows data in an editor of which usually multiple instances are open. In an additional view you can edit the editor-values. When the values are changed in the view they are updated in the editor and it's dirty flag is set.
So far it works fine. What we're missing is: When another editor instance gets the focus, our view should show the data of this editor.
I managed to do that for two views. The second view is sucessfully updated using a TableViewer as selection Provider and registering a SelectionListener in the other view. I tried the same thing for the editor using a Viewer I subclassed from ContentViewer, but it didn't work.
Can this approach be working?
Or do I need a different approach on the problem?
May be you can subclass your view from PageBookView and then provide special adapter for your editor. Outline View is implemented using this approach.
Thank you cerealk, that was exactly what I needed. :-)
Update the View when another Editor is selected
public class myView {
// Create an IPartListener2
IPartListener2 pl = new IPartListener2() {
// If the Editor I'm interested in was updated ...
public void partActivated(IWorkbenchPartReference ref) {
IWorkbenchPart part = ref.getPart(true);
if (part instanceof DetailEditor) {
// ... update the view
Contact contactFromSelectedEditor = ((DetailEditor) part).detailComposite.contact;
detailComposite.update(contactFromSelectedEditor);
}
}
...
}
// Add the IPartListener2 to the page
IWorkbenchPage page = this.getSite().getPage();
page.addPartListener(pl);
}
Why use an IPartListener2 instead of an IPartListener
The IPartListener2 replaces IPartListener with 3.5.
As explained in this this answer:
You should always use IPartListener2 as it can handle part-change events on parts that have not yet been
created because they are hidden in a stack behind another part.
This
listener will also tell you when a part is made visible or hidden or
when an editor's input is changed.