Data does not show in Design Mode - mvvm-light

I have my models, viewmodels and views setup and binding properly when the program runs, but when in design mode I do not see any of the data or dynamic elements that are controlled by the data. What could I be missing. I looked at the sample friends application and did not see anything I was doing different. Any help will be appreciated.

The design view does not support connections to your database, so if your view model constructors are loading any data from a database then this will cause an exception when switching to design view. Consequently, your UI elements will not load properly.
You will, instead, need to load dummy data if your in design mode. You can progamatically check whether or not you're in design mode by using the MVVM-Light Toolkit's ViewModelBase.IsInDesignModeStatic property.
For example:
ViewModelConstructor()
{
if (ViewModelBase.IsInDesignModeStatic)
{
// load dummy data
}
else
{
// load real data from database
}
}

Usually you need to DEBUG why design data is not shown. In most cases, it is because exceptions are thrown somewhere in your code when the designer is executing them. As mentioned by Laurent in his videos, one way is to attach to your Blend process in Visual Studio. I tried this approach in my project and it worked perfectly.

Related

MVVMCross BindingContext is Null when not using MvxContentPage

I have an issue where several of my pages are using the SfBackdropPage control from Syncfusion. This control requires the page to have a base of SfBackdropPage and not the usual ContentPage otherwise it just won't work.
To make MVVMCross work, the page needs have a base such as MvxContentPage
You see where this is going ?
I opened a ticket with Syncfusion to see if they could work around this issue but basically they just said its not possible. So since I needed to have that control as part of the page I had to leave the base as it was.
How do I setup MVVMCross to work with these pages without having the page inherit from MvxContentPage ?
I've used the following in the setup.cs in the Android project:
protected override IMvxViewsContainer InitializeViewLookup(IDictionary<Type, Type> viewModelViewLookup)
{
viewModelViewLookup.Add(typeof(SitesViewModel), typeof(SitesView));
return base.InitializeViewLookup(viewModelViewLookup);
}
I can navigate to the page but I get a null reference exception due to the binding context not been set. I've tried to set this in the XAML but it requires a parameterless constructor but that's not possible as the view model uses Dependency Injection as it relies on these object been passed in.
Can anyone give any pointers, I'm still learning MVVMCross so hopefully I've just missed something.
XF: 4.8.0.1687
MVVMCross: 7.1.2
UPDATE 1:
I've tried to find something in the MVVMCross source to see how it does the setup for the binding context, but I've not found anything. So for now, I'm manually creating the binding context in the page code behind and using Mvx.IocProvider.Resolve<> to pass the required interfaces.
I'm not sure if this is the best to workaround this issue but it works. Maybe there is a better way ?
UPDATE 2:
It seems that update 1 route is no good as the doing this creates a new instance of the VM which is to be expected but an instance already exists which is created by the MVVMCross framework. The question is how do I get the VM instance from the code behind ? The only way I have found so far is to use IMvxOverridePresentationAttribute and the cast the request to MvxViewModelInstanceRequest which then allows access to the VM instance which I assign to the binding context. I may be better off creating another question as to the best approach for this method.

Does Xamarin Forms have memory leak on UWP?

I wrote UWP but this can be also on Android on IOS because I profiled only UWP application using VS2017.
Steps to create problem.
- Open VS 2017 and start a new xamarin forms project by selecting tabbed page or masterdetail page. No need to write any single code.
Problem;
First snapshot is after application is loaded.
2nd one has taken after selecting an item in the list and navigating to the ItemDetailsPage
3rd snapshot was taken after navigating back to ItemsPage
Expections; to not see ItemDetailsPage on 3rd snapshot because I am navigating back and this page is popped from the navigation stack. so it should be removed, collected by GC or disposed.
Here is the 3rd snapshot details;
Do I read this snapshot wrong or there is something wrong with the xamarin forms applications?
EDIT: Below screenshot also stats that there is "cycle detected". what does that mean? i thought cycles cause memory leaks, dont they?
not see ItemDetailsPage on 3rd snapshot because I am navigating back and this page is popped from the navigation stack. so it should be removed, collected by GC or disposed.
If you try navigating to different detailed pages then come back and take a snapshot again, you will find the count of ItemDetailPage stays 1.
Sometimes, for performance's sake, objects like page or resources will be properly cached and reused. If you have a page which contains large images or resources, you should try to dispose them manually to reduce memory usage.
Update:
Now question is how to properly dispose it? where to do that? I keep reading OnDissapearing method which is not safe for me as it can be called on navigating forward , not only navigating back in the stack. what is your suggestion for that?
If you don't want to dispose your resources for navigating forward, you can define a status parameter when navigating forward, do not dispose the resource. ex:
bool forwardNavigating=false;
...
protected override void OnDisappearing()
{
base.OnDisappearing();
if (!forwardNavigating)
{
//dispose your resources
}
}
elow screenshot also stats that there is "cycle detected". what does that mean? i thought cycles cause memory leaks, dont they?
cycle detected means:
An object can reference a second object that directly or indirectly holds a reference to the first object.
Please refer to Circular references of Analyze .NET Framework memory issues.
Personal thought:
I don't think it is a memory issue in terms of cycle detected. Under some situations we may need to visit parent object when we are in it's children. Thus we need a property Parent while the parent is still referencing the children. This happens a lot in views. I don't know how the analyzer works and whether it is the situation I described above. What I want to say is cycle detected doesn't equals Memory Leaks.
The same memory leak happens while dynamically changing the BindingContext (Reset the BindingContext by setting null and reassign the new view model) in Xamarin ListView. Does anyone come across this issue

Relating two shield UI ASP.NET Charts

I want to create two related Shield UI ASP.NET charts. When the users clicks on the first one, the data on the second one to be changed. I looked at the available events in my Visual Studio, however what i find are events related to the data binding, loading and so on. I also see there is a group of properties- ClientEvents. And for the SeriesClick event i declare the SeriesClickFunction. Which is located in my C# code:
protected void SeriesClickFunction() {
}
However when i run my application in debug mode and put a break on that function, it never gets triggered. Why is that? How could I actually take use of these events?
In the C# code module you may not place the ClientEvents functionality. What you need is to place it on the HTML source of your page. Here is one good example of how you may relate two charts in the manner you want:
https://demos.shieldui.com/aspnet/rangebar-chart/related-charts

MVVM Light + Blend designer view error: Cannot find resource named 'Locator'.

The application runs fine but i could not see my design in the designer view.
It says Cannot find resource named 'Locator'. Obviously, i did not change anything in the code, i just did the data binding using the data binding dialog...
anyone facing the same problem?
There are two known occurrences where this can happen.
If you change to Blend before you built the application, the DLLs are not available yet and this error can be seen. Building the application solves the issue.
There is a bug in Expression Blend where, if you are placing a user control in another user control (or Window in WPF), and the inner user control uses a global resource, the global resource cannot be found. In that case you will get the error too.
Unfortunately I do not have a workaround for the second point, as it is a Blend bug. I hope we will see a resolution for that soon, but it seems to be still there in Blend 4.
What you can do is
Ignore the error when working on the outer user control. When you work on the inner user control, you should see the design time data fine (not very satisfying I know).
Use the d:DataContext to set the design time data context in Blend temporarily.
Hopefully this helps,
Laurent
I've come up with a reasonably acceptable workaround to this problem since it doesn't appear to have been fixed in Blend 4:
In the constructor for your XAML UserControl just add the resources it needs, provided you're in design mode within Blend. This may be just the Locator, or also Styles and Converters as appropriate.
public partial class OrdersControl : UserControl
{
public OrdersControl()
{
// MUST do this BEFORE InitializeComponent()
if (DesignerProperties.GetIsInDesignMode(this))
{
if (AppDomain.CurrentDomain.BaseDirectory.Contains("Blend 4"))
{
// load styles resources
ResourceDictionary rd = new ResourceDictionary();
rd.Source = new Uri(System.IO.Path.Combine(Environment.CurrentDirectory, "Resources/Styles.xaml"), UriKind.Absolute);
Resources.MergedDictionaries.Add(rd);
// load any other resources this control needs such as Converters
Resources.Add("booleanNOTConverter", new BooleanNOTConverter());
}
}
// initialize component
this.InitializeComponent();
}
There may be some edge cases, but its working OK for me in the simple cases where before I'd get a big red error symbol. I'd LOVE to see suggestions on how to better solve this problem, but this at least allows me to animate user controls that otherwise are appearing as errors.
You could also extract out the creation of resources to App.xaml.cs:
internal static void CreateStaticResourcesForDesigner(Control element)
{
if (AppDomain.CurrentDomain.BaseDirectory.Contains("Blend 4"))
{
// load styles resources
ResourceDictionary rd = new ResourceDictionary();
rd.Source = new Uri(System.IO.Path.Combine(Environment.CurrentDirectory, "Resources/Styles.xaml"), UriKind.Absolute);
element.Resources.MergedDictionaries.Add(rd);
// load any other resources this control needs
element.Resources.Add("booleanNOTConverter", new BooleanNOTConverter());
}
}
and then in the control do this BEFORE InitializeComponent():
// create local resources
if (DesignerProperties.GetIsInDesignMode(this))
{
App.CreateStaticResourcesForDesigner(this);
}
Note: At some point in time this stopped working for me and I ended up hardcoding the path to the Styles.xaml because I got frustrated trying to figure out which directory I was in.
rd.Source = new Uri(#"R:\TFS-PROJECTS\ProjectWPF\Resources\Styles.xaml", UriKind.Absolute);
I'm sure I could find the right path with 5 minutes work, but try this if you're at your wits end like I was!
In MyUserControl.xaml, instead of:
DataContext="{Binding Main, Source={StaticResource Locator}
use:
d:DataContext="{Binding Main, Source={StaticResource Locator}
where "d" has been previously defined as:
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
The reason and workaround explained here
http://blogs.msdn.com/b/unnir/archive/2009/03/31/blend-wpf-and-resource-references.aspx
Look at (b) part of the post.
I had a similar problem with a user control resource.
I added this in my usercontrol xaml code:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/GinaControls;component/Resources/GinaControlsColors.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
Where GinaControls is the namespace where the control class is declared and /Resources/GinaControlsColors.xaml is the project folder and xaml resource file name.
Hope this helps.
Just add this in your App.xaml.cs at the very beginning
here's my piece of code
[STATThread()]
static void main(){
App.Current.Resources.Add("Locator", new yournamespace.ViewModel.ViewModelLocator());
}
public App(){
main();
}
Make sure the Blend has opened the entire solution and NOT just the single project containing the views. I was right-clicking in Visual Studio and selecting Open In Expression Blend. To my surprize, Blend could not find the solution file, so it only opened the single project.
When I realized this, I launched Blend directly, pointed it to the solution file, and then Blend was able to find the ViewModelLocator in my view.

How do I unload a externally loaded SWF file from a SWFLoader component in Adobe Flex?

I have an application that loads external SWF files and plays them inside a Adobe Flex / Air application via the SWFLoader Flex component. I have been trying to find a way to unload them from a button click event. I have Google'd far and wide and no one seems to have been able to do it without a hack. The combination of code I see people use is:
swfLoader.source = ""; // Removes the external link to the SWF.
swfLoader.load(null); // Forces the loader to try to load nothing.
// Note: At this point sound from the SWF is still playing, and
// seems to still be playing in memory.
flash.media.SoundMixer.stopAll();
// Stops the sound. This works on my development machine, but not
// on the client's.
If the SWFs are closed (hidden) this way, eventually the program crashes.
Any ideas? I have found tons of posts in various forums with people having the same problem. I assume I will get one wrong/incomplete answer here, and than my post will sink into nothingness as usual, but either way, thanks in advance!
Edit 1: I can't edit the actual SWF movies, they're created by the client. If I can't close any SWF opened through Flex, isn't that a problem with the Flex architecture? Is my only option sending the SWFs to the web browser?
... isn't that a problem with the Flex architecture?
Yes it is, and it also affects Flash in general. Until you can take advantage of the Loader.unloadAndStop() method in FP10 (AIR 1.5), you can't guarantee that externally loaded content will not continue to consume memory and cpu resources, even if you use the Loader.unload() method. (To be honest, I'm not 100% sure that even that will guarantee freeing of resources, but maybe I'm a pessimist.)
The next best thing is for you to insist that the creators of the content you load adhere to a set of guidelines, including exposing something like a dispose() method which your app can call to ask it to release as many resources as possible before you unload() it. If this isn't possible, then your application will almost definitely bloat in memory and cpu usage each time you load an external swf. Sorry.
If it makes you feel any better, you're not alone. ;)
It is a problem that a badly created SWF can sink your application, and many of the issues with this will be fixed in Flash Player 10, as others have mentioned. However, regardless of platform you will always risk having problems if you load third party code, there's always the possibility that it contains bugs, memory leaks or downright malicious code. Unless you can load content into a sandbox (and you can't in Flash, at least not yet), loading bad things will sink your app, it's as simple as that.
I'm sorry to say that unless you can guarantee the quality of the loaded content you can't guarantee the quality of your own application. Flash developers are notorious for writing things that leak, or can't be unloaded, because Flash makes it easy to do the wrong thing, especially for things that live on the time line. Loading any Flash content that you don't have control over directly is very perilous.
The best solution is
swfLoader.autoLoad = false;
swfLoader.unloadAndStop();
swfLoader.autoLoad = true;
In this way you stop the player, unload the content from memory and avoid the sound to remain playing..
Cheers
The problem resides in the loaded swf, it simply does not clean up the audio after itself.
Try attaching an unload event onto movieclips like this:
MovieClip(event.target.content).loaderInfo.addEventListener(Event.UNLOAD, unloadMovieClipHandler);
private function unloadMovieClipHandler(event:Event) : void
{
SoundMixer.stopAll();
}
I'd generally stay away from SWFLoader and use the classes in the mx.modules package.
Flex has a module system that enables this type of behavior. You can check it out here : http://livedocs.adobe.com/flex/3/html/help.html?content=modular_3.html . In general, dynamically loading and unloading swf components is tricky, especially if those modules modify any global state in the application (styles, etc..). But if you create an interface for your modules, and then each class you load/unload implement that interface as well as extend the flex module class, you can load and unload them cleanly.
Try the following:
try {
new LocalConnection().connect('foo');
new LocalConnection().connect('foo');
} catch (e:*) {}
That will force a Garbage Collection routine. If your SWF is still attached, then you've missed some sort of connection, like the audio.
There are a couple ways to force GC, which all kind of suck because they spike CPU, but the good news is that an official way is coming in Flash Player 10:
unloadAndStop
link: http://www.gskinner.com/blog/archives/2008/07/unloadandstop_i.html
Until then, I'm afraid you'll have to force it with hacks like I showed above.
You have not shown all of your code so I am going to assume you didn't use the unload method of the Loader class. Also swfLoader.load(null) seems wrong to me as the load method is expecting a URLRequest object. When you want to clean things up at the end, set the object's value to null instead of calling a null load. The fact that your still hearing audio indicates that your data wasn't unloaded, or the audio file does not reside inside the content that was unloaded. Lets walk through this.
Example below
var loader:Loader = new Loader();
var request:URLRequest = new URLRequest('test.swf');
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onSwfLoad, false, 0, true);
function onSwfLoad(e:Event):void
{
addChild(loader);
loader.contentLoaderInfo.addEventListener(Event.UNLOAD, onLoaderUnload, false, 0, true);
loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onSwfLoad, false);
}
function onLoaderUnload(e:Event):void
{
trace('LOADER WAS SUCCESSFULLY UNLOADED.');
}
//Now to remove this with the click of a button, assuming the buttons name is button_mc
button_mc.addEventListener(MouseEvent.MOUSE_DOWN, onButtonDown, false, 0, true);
function onButtonDown(e:MouseEvent):void
{
loader.unload();
loader.contentLoaderInfo.removeEventListener(Event.UNLOAD, onLoaderUnload);
//When you want to remove things completely from memory you simply set their value to null.
loader = null;
button_mc.removeEventListener(MouseEvent.MOUSE_DOWN, onButtonDown);
}
I do hope that this was helpful, and I am sorry if it was redundant, but without seeing your code I have no way of knowing exactly how you approached this.

Resources