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

后端 未结 7 1039
忘掉有多难
忘掉有多难 2020-12-31 00:23

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

相关标签:
7条回答
  • 2020-12-31 00:55

    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.

    0 讨论(0)
  • 2020-12-31 00:57

    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.

    0 讨论(0)
  • 2020-12-31 01:07

    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

    0 讨论(0)
  • 2020-12-31 01:08

    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.

    0 讨论(0)
  • 2020-12-31 01:09

    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 **

    1. 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

    2. 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.

    3. 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

    4. 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 **

    1. 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

    2. 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.

    3. 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 **

    1. 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).

    2. 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...

    3. ... 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
    0 讨论(0)
  • 2020-12-31 01:11

    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.

    0 讨论(0)
提交回复
热议问题