Trouble with ImageDownloadService - codenameone

Earlier I was using the static createImageToStorage() method and it was working fine, but I wasn't able to get the scaling the way I wanted so I decided to create an instance of the class and use the non-static methods. Here's my code:
Label myLabel = findMyLabel();
ImageDownloadService imgService = new ImageDownloadService(URL_PREFIX+"images/"+picPath, myLabel);
imgService.setDownloadToStyles(true);
NetworkManager.getInstance().addToQueue(imgService);
The picture doesn't load, and when I debugged the InputStream provided by ReadResponse() had no data. What am I doing wrong?

It should be set to the bgImage of the style because of the setDownloadToStyles. I would recommend you use URLImage which is better designed with regard to scaling behavior.

Related

Form subclasses in codename one

I'm building an app in Codename one. I'm trying to both create a Form in the codename one resource GUI and specify its type used in code. Background is to be able to specify dynamically which data is used in the form.
Is this recommended and is there a recommended way to accomplish that?
Currently I'm digging into the codenameone code and it looks like one way would be to pass a custom-made resource to the StateMachine/UIBuilder. The UIBuilder asks the resource for the component type and use this to return a custom type,
and register the custom form types with lines like
UIBuilder.registerCustomComponent("MyForm",com.myapp.MyForm.class);
Any suggestions to this?
Right now the only way to do this in the old GUI builder is to replace all the forms with your new Form subclass which could be fine for many cases. E.g. override this in the state machine:
protected Component createComponentInstance(String componentType, Class cls) {
if(cls == From.class) {
return new MyForm();
}
return super.createComponentInstance(componentType, cls);
}
Notice that we are in the process of moving to a new more traditional GUI builder, right now its in technology preview state (translation: buggy as hell and lots of missing features) but this should be trivial in the future. See:
https://www.codenameone.com/blog/new-gui-builder.html
https://www.codenameone.com/blog/gui-builder-walkthru.html
https://www.codenameone.com/blog/terse-syntax-migration-wizard-more.html

How do I work with images in a portable class library targeting Windows Store Apps and WP7,WP8,WPF?

I am working on a first PCL that targets : WSA (Windows Store Application), WPF,WP7,WP8. We can say that it is a rolerdex kind of application, you have contacts , they have contact details and images. (it's not, but I can't give details about the application, so I am using a very simple example instead). Here are some of my questions :)
Should I have the images in the PCL?
If yes:
How do reference the image for usage in WSA?
How do I best solve scaling with the scale qualifiers etc. when used across different projects?
I am not using a database and the images are not downloaded from an external service- I would like to keep the images (not many really) locally, in the app or in the PCL.
EDIT:
I just want to display images. That's it. It's a static rolerdex, you can't add new people. I just want to display 5 number of people and their image (in the PCL). How do I reference the images if it's a Windows Store Application?
I have a binding and the DataContext is set to a ViewModel in the PCL. The ViewModel aggregates the data to be displayed from the models. The property I've bound against is MyImage. Ignoring the other platforms, how would the Uri look like? Everything else works fine.
I really just want help with these three questions, although I really appreciate all the answers!!!
For a lot of cases, images are platform-specific. They need to cater for size and DPI of the device itself, and would need to fit in with the look and feel of the application. For these situations, I would have the View itself decide what images to show to the user, probably based on some sort of state/mode provided by the ViewModel.
However, these are cases where the images need to come from the ViewModel, for example, in the case of the sender thumbnails that get displayed in mail applications. In these cases, I have the ViewModel return some sort of a platform-agnostic concept of an image (such as byte[]), and then have the platform-specific projects convert that into something that their UI stack understands (in XAML, this would be a ImageSource).
The code would look something like this:
Portable project:
using System.IO;
using System.Reflection;
namespace Portable
{
public class ViewModel
{
private byte[] _image = LoadFromResource("Image.png");
public byte[] Image
{
get { return _image; }
}
private static byte[] LoadFromResource(string name)
{
using (Stream stream = typeof(ViewModel).GetTypeInfo().Assembly.GetManifestResourceStream("Portable." + name))
{
MemoryStream buffer = new MemoryStream();
stream.CopyTo(buffer);
return buffer.ToArray();
}
}
}
}
Note: You will need to remove or add GetTypeInfo() depending on the platforms you are targeting.
Here we're reading from an embedded resource (Properties -> Build Action -> Embedded Resource), but you could imagine this coming from the network, or somewhere else.
Windows Store app project:
In the Windows Store app, you would have a value converter to convert from byte[] -> ImageSource:
using System;
using System.IO;
using Windows.Storage.Streams;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media.Imaging;
namespace App
{
public class ByteToImageSourceValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
InMemoryRandomAccessStream s = new InMemoryRandomAccessStream();
byte[] bytes = (byte[])value;
Stream stream = s.AsStreamForWrite();
stream.Write(bytes, 0, bytes.Length);
stream.Flush();
stream.Seek(0, SeekOrigin.Begin);
BitmapImage source = new BitmapImage();
source.SetSource(s);
return source;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
}
In the code behind of the View, set the DataContext:
DataContext = new ViewModel();
Then in the View itself binding to the ViewModel.Image property, and set the converter:
<Page.Resources>
<local:ByteToImageSourceValueConverter x:Name="ImageConverter"/>
</Page.Resources>
<Grid >
<Image HorizontalAlignment="Left" Height="242" Margin="77,10,0,0" VerticalAlignment="Top" Width="278" Source="{Binding Image, Converter={StaticResource ImageConverter}}"/>
</Grid>
Images are indeed quite problematic when you need to scale them across different platforms with different pixel densities and different screen sizes.
Coupled with this, there are often problems with image manipulation libraries not being portable - especially when they use hardware acceleration on each platform.
Assuming that your rolodex app is somehow going to allow users to capture images, and then to upload them to some shared database/service for later viewing, here's how I might approach the problem. It's not the only solution - there's no "one right way" here!
** Capturing and uploading images **
For capturing the picture (either from a folder or from a camera) I would have to use a native hook for each platform - so NOT PCL for this part
If I then needed to do some on-device processing of the image (e.g. resizing or adding a thumbnail) then again this would probably be done differently on each platform - so NOT PCL.
Once you have the photo (e.g. as a JPEG encoded in a MemoryStream) and want to upload it to a server, then I would probably do this using the asynchronous handlers HttpWebRequest (these are the old methods, nothing to do with async/await) in common PCL code
What's running on the server.... well, that's almost certainly not PCL code - and I might use methods there to resize the image into device ready sizes - e.g. different size thumbnails
** Showing images **
When I need to display someone's image from the database, then I would probably get the server to return a list of available thumbnail URLs - this is server code so would be not PCL
The app code that actually asks for the list of contacts or the contact detail - that would probably be PCL code - and would probably use HttpWebRequest again.
The View code that takes the contact and renders it on the screen? That would probably be XAML - and I would just use the native Image control on each platform to consume and render an appropriate thumbnail for the situation.
** If you were storing the images locally **
If you were storing the images locally instead of using a central server, then you'll probably need to use non-PCL code for this too. Each platform has the same basic type of methods: LoadFile, SaveFile, etc - and each will provide mechanisms to create, enumerate, read and write folders and files, but each platform does this via a different API to the file system (e.g. System.IO in WPF, IsolatedStorage in WP7 Silverlight, etc).
Once you've got your files into a common(ish) structure, then the PCL control code will be able to treat each file as just a pair of strings - the folder it's in and the file name...
... and in your UI layer (e.g. XAML) you will probably be able to reference those image files directly - probably can be done using a specific ValueConverter to generate the correct filename or filestream on each platform - e.g. in wp7 you could use the converter from Windows Phone 7 Silverlight binding image from the IsolatedStorage
So, my summary is:
I'd use PCL code wherever I could
but in reality that PCL code is only going to be in the control and networking - not in the image collection, image processing or image rendering
Some other things that might help:
currently I find it's quite hard to mix .Net4.5 async/await code with "normal" code - so even sharing the networking code might be quite hard to do - you might actually save time if you write separate code for everything :(
to help share the code, I would definitely try to use some form of IoC or DI to try to inject specific implementation of platform specific code where it's needed (this is what I do a lot in MvvmCross - and it's what #dsplaisted talks about in service location in http://blogs.msdn.com/b/dsplaisted/archive/2012/08/27/how-to-make-portable-class-libraries-work-for-you.aspx
I tend to agree that image handling should probably be platform specific. Just as a general rule anything view related should not be included in a PCL. The above answers have some great technical detail that I will not bother repeating, but wanted to post a link to a slide deck I put together to discuss principals of using PCL. http://prezi.com/ipyzhxvxjvp-/sharing-is-caring-code-reuse-in-xaml-applications/
Hopefully this gives some general guidance on the overall design strategies and reinforces the information in the previous answers.
Most people have already said and the answer is also "Not possible". UI elements in PCL goes against the philosophy of PCL, which should be usable as is across platforms that you are targetting.
Here's what MSDN has to say on PCL - "the Portable Class Library project doesn't contain any UI components because of behavioral differences between the UIs of different devices" (from http://msdn.microsoft.com/en-us/library/gg597391.aspx)
hope this helps
My first instinct is to say no you shouldn't have images in your PCL given what you have described.
But if I were going to do it images can be stored via resources in the different libraries and you can store a different image for each platform in there and then do an Environment inspection to determine what image to pull out. But this approach really only should be attempted if you need scale.
By scale I mean you are open sourcing this library where 1000's of programs are going to use it. If this is for your own internal use for 3 or 4 apps, I would say don't bother save your self the headache. Just pass the image into the shared library or set it via a config and be done with it.
Or just don't manage images via the PCL. Because image manipulation changes and is different on every platform, especially the ones you mentioned. And you are bound to run into some weird bug where it just doesn't work the same as it does on the other platforms.
I would probably put the actual image files in each app. I don't think you get much value out of trying to embed them in the PCL.
In your portable ViewModels, you can reference the image via a Uri. Unfortunately that Uri needs to be different on each platform. For Windows Store apps it needs to be something like ms-appx:////Assets/image.png where for Windows Phone I think it will just be /Assets/image.png.
So you'll need some code to figure out the correct Uri format. That could be a platform-specific service with a portable interface that the ViewModels would call. You might also be able to create a binding converter that would do whatever conversion you needed.
There are certainly other ways of doing this-- this is just what I'd picked based on the information in your question.
you can put the image on the view model as type "object" and use an interface (which is injected) to create the bitmap.
public interface IBitMapCreator
{
object Create(string path);
}
public class MyViewModel
{
private bool _triedToSetThumb;
private readonly IBitMapCreator _bc;
public MyViewModel(IBitMapCreator bc, string path)
{
_bc = bc;
SetThumb(path);
}
public object Thumb { get; private set; }
private void SetThumb(string path)
{
try
{
if (!_triedToSetThumb)
{
string ext = Path.GetExtension(path).ToUpper();
if (
ext == ".JPG" ||
ext == ".JPEG" ||
ext == ".PNG" ||
ext == ".GIF" ||
ext == ".BMP" ||
false
)
{
Thumb = _bc.Create(path);
OnPropertyChanged(new PropertyChangedEventArgs("Thumb"));
}
}
}
finally
{
_triedToSetThumb = true;
}
}
}
in the WPF version, you could do this
class BitMapCreator : IBitMapCreator
{
public object Create(string path)
{
return BitmapFrame.Create(new Uri(path));
}
}
By using this method you can data bind right to the image and do not need a converter.

How do I code a MVC3 Helper

I’ve just build my first Helper in MVC, it’s very basic and just displays a string where ever I use it. So it’s a .cshtml file in my App_Code folder, I think that is how it's supposed to be set up, with the following code in it,
#helper DisplaySelect() {
#:This text is coming from an helper class.
}
Now I am a wiz with helpers how do I make it do things. E.g.. say I want it to query the database and display something, I would normally do that work in my controller. How do I do that with helpers, do I create a helper controller and then treat the helper like a partial view???
Any help would be greatly appreciated.
Cheers,
Mike.
Thanks guys,
I’ve asked that question before Shark “Why would you use a helper and not a partial view” the answer I got there was a partial view is more for just displaying common HTML where as a Helper can have a bunch of code in it and do all kinds of great processing stuff. Now it seems that’s not true and they are pretty much the same thing, in some respect, except in Link664’s case!
I like what you’re saying Link664 that makes sense as it cleans up the code nicely.
What I was going to do was try and populate a drop down list in a helper and then use it in multiple places, but from my research today that’s not what helpers are for.
Cheers,
Mike.
I'm a bit confused by what you want to do and why you want to do it but I'll give it a go. As you mentioned, you would normally do that work in your controller. It is very poor design to make database calls from a partial view/html helper created client-side.
The #helper syntax is to be used only for simplifying view code, not for implementing code that should be in the controllers or models in the view. See this article for a better idea of when you should be using them.
As for your example, I recommend you pass the data that you want from your controller and create an extension method on HtmlHelper to render it in your view. For example if you wanted to display a list of the most recent 10 posts on your view:
public static HtmlString RecentPostsDisplay(this HtmlHelper html, string name,
List<Post> values, object htmlAttributes)
{
var tag = new TagBuilder("ul");
...
//build list content by looping through values and adding to TagBuilder
...
return new HtmlString(tag.ToString(TagRenderMode.SelfClosing));
}
and in your controller
public ActionResult Blah()
{
ViewBag.posts = _db.GetMostRecentPosts();
return View();
}
Then in your view you can put
#Html.RecentPostsDisplay(ViewBag.RecentPosts)
Hopefully that is what you are looking for, if not update your question so it's not so ambiguous and I'll try again!

Sharing Linq to SQL DataContext between WP7.1 and WPF apps?

I have built a WP7.1 application that uses a local database. I used sqlmetal to generate the data context as per this article. http://blogs.microsoft.co.il/blogs/alex_golesh/archive/2011/05/24/windows-phone-mango-what-s-new-local-database-part-1-of-8.aspx
This works as expected using this in the ViewModel.
context = new BirdsnBflysDC("DataSource='isostore:BirdsnBflys.sdf'");`
I am now attempting to "share" the Model and ViewModel code with a WPF application. Initially I added the appropriate files as a link to the WPF project. Creating an instance of the context didn't work so as a test I have added just the data context code to a WPF project and attempt to create an instance of the context in the Loaded event handler as follows.
BirdsnBflysDC context = new BirdsnBflysDC("DataSource='C:\BirdsnBflys.sdf'");
DataContext = context;
The code actually has the complete path to the database. When I step through this in the debugger the context initialization in the data context quits running as if there was an exception, the second line of code above is never reached and the WPF window is shown as if things completed correctly.
I've tried several variation in the DataSource string including "|DataDirectory|\\BirdsnBflys.sdf" all with the same result.
Any suggestions as where to go with this? How to figure out what isn't working correctly?
Thanks,
Dave
The problem is that what is expected in the connection string is different for the two environments.
WP7 works with this.
context = new BirdsnBflysDC("DataSource='isostore:BirdsnBflys.sdf'");
WPF works with this.
context = new BirdsnBflysDC("|DataDirectory|\BirdsnBflys.sdf");
If you give WPF a file name that isn't there you get no error information, the instantiation of the data context fails quietly and any additional code does not get executed.
Dave
Did you remove the 2 methods from the generated cs file? I mean the methods unsupported by mango.
public ExternalDB(System.Data.IDbConnection connection) :
base(connection, mappingSource)
{
OnCreated();
}
public ExternalDB(System.Data.IDbConnection connection,
System.Data.Linq.Mapping.MappingSource mappingSource) :
base(connection, mappingSource)
{
OnCreated();
}
I am not sure about this, but they might be needed for wpf.
Hope this helps.

Change Default Winform Icon Across Entire App

Can I change the default icon used on a Winform?
Most of my forms have their icon property set to a custom icon. For the few forms that slip through the cracks, I don't want the generic "hey look, he made this in visual studio" icon.
One solution is to tediously check every one of my forms to make sure they either have a custom icon set or have ShowIcon set to False.
Another solution is to have every one of my forms inherit from a base class that sets a custom icon in the constructor.
Aside from those solutions, what other options do I have?
EDIT:
I was hoping there would be a way to replace the source of the stock icon with my own. Is it in a resource file somewhere? Or is it embedded in a .NET dll that I can't (or really, really shouldn't) modify?
BOUNTY EDIT:
Is there a way to accomplish this without editing or writing a single line of code? I don't care how impractical, complicated, waste-of-time the solution is... I just want to know if it's possible. I need to satisfy my curiosity.
The default icon is embedded in the winforms dll - looking at reflector (DefaultIcon) it is:
defaultIcon = new Icon(typeof(Form), "wfc.ico");
There is no magic in there that checks another common location, so you can't do it without changing code.
You could always embrace the forces of darkness with field-based reflection? Note: this is hacky and brittle. On your own head! But it works:
[STAThread]
static void Main() {
// pure evil
typeof(Form).GetField("defaultIcon",
BindingFlags.NonPublic | BindingFlags.Static)
.SetValue(null, SystemIcons.Shield);
// all forms now default to a shield
using (Form form = new Form()) {
Application.Run(form);
}
}
To do it properly; two common options;
a base Form class which has the icon set
a factory Form method - perhaps something like:
code:
public static T CreateForm<T>() where T : Form, new() {
T frm = new T();
frm.Icon = ...
// any other common code
return frm;
}
Then instead of:
using(var frm = new MySpecificForm()) {
// common init code
}
Something like:
using(var frm = Utils.CreateForm<MySpecificForm>()) {
}
Of course - that isn't much prettier! Another option might be a C# 3.0 extension method, perhaps as a fluent API:
public static T CommonInit<T>(this T form) where T : Form {
if(form != null) {
form.Icon = ...
//etc
}
return form;
}
and
using(var frm = new MySpecificForm().CommonInit()) {
// ready to use
}
This is then just a .CommonInit() away from your existing code.
The base class option is the one that we use.
If you are looking for an alternative (not necessarily good ones), you could:
1. Use IOC to instantiate all of your forms and modify the IOC container to set the application icon.
2. Use AOP to insert code into all of the forms that sets the application icon.
Personally, I'd just use the base class...
My useful answer:
No
Would be a nice feature for microsoft to implement though, since most apps use the same icon across the entire application.
If you want to update all the icons by another one, you can build a small app that edits all the *.Designer.vb files (in vb.net) and adding the folowing line to InitializeComponent:
Me.Icon = New System.Drawing.Icon("C:\PathTo\icon.ico")
Hope it helps.
If all your forms are in just one project then you can take the dll of the project and use reflection to get every type in the dll. If the type derives from Form you can set the type's Icon property to whatever you want. I am not sure what the performance overhead will be if the project is very big.

Resources