I have applications on WP8, it contains images loaded from the server. Pictures are changing on server but have the same name and the same url. After the change, the phone still displays the previous pictures. How to solve this problem.
This is due to built in resource caching, which affects both remote requests as well as requests for local image resources in your application. When declaring your image control markup, you can disable caching by creating its source property manually. For instance:
<Image>
<Image.Source>
<BitmapImage UriSource="{Binding ContentPath}"
CreateOptions="IgnoreImageCache" />
</Image.Source>
</Image>
Well, the phone caches the images that are downloaded. If you wanna set a new image you have to "clean" the image source. Your questions is not given me inave information, but from what i understand, one simple converter should do the trick:
public class CacheImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string path = value as string;
Uri imageFileUri = new Uri(path, UriKind.Absolute);
BitmapImage bm = new BitmapImage(imageFileUri);
return bm;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
XML
<phone:PhoneApplicationPage.Resources>
<imgConv:CacheImageConverter x:Key="ConvertNew" />
</phone:PhoneApplicationPage.Resources>
...
<Image Source="{Binding strPath, Converter={StaticResource ConvertNew}}"/>
Related
I am using PrimeFaces 5.3 <p:fileUpload> to upload a PNG image and I would like to show a preview of it in <p:graphicImage> before saving in database.
Here's a MCVE:
<h:form enctype="multipart/form-data">
<p:fileUpload value="#{bean.uploadedFile}" mode="simple" />
<p:graphicImage value="#{bean.image}" />
<p:commandButton action="#{bean.preview}" ajax="false" value="Preview" />
</h:form>
private UploadedFile uploadedFile;
public UploadedFile getUploadedFile() {
return uploadedFile;
}
public void setUploadedFile(UploadedFile uploadedFile) {
this.uploadedFile = uploadedFile;
}
public void preview() {
// NOOP for now.
}
public StreamedContent getImage() {
if (uploadedFile == null) {
return new DefaultStreamedContent();
} else {
return new DefaultStreamedContent(new ByteArrayInputStream(uploadedFile.getContents()), "image/png");
}
}
No error occurring on the backing bean, and the image won't be load and display at front-end. The client mentions that the image returned a 404 not found error.
Your problem is two-fold. It failed because the uploaded file contents is request scoped and because the image is requested in a different HTTP request. To better understand the inner working, carefully read the answers on following closely related Q&A:
Display dynamic image from database with p:graphicImage and StreamedContent
How to choose the right bean scope?
To solve the first problem, you need to read the uploaded file contents immediately in the action method associated with the form submit. In your specific case, that would look like:
private UploadedFile uploadedFile;
private byte[] fileContents;
public void preview() {
fileContents = uploadedFile.getContents();
}
// ...
To solve the second problem, your best bet is to use the data URI scheme. This makes it possible to render the image directly in the very same response and therefore you can safely use a #ViewScoped bean without facing "context not active" issues or saving the byte[] in session or disk in order to enable serving the image in a different request. Browser support on data URI scheme is currently pretty good. Replace the entire <p:graphicImage> with below:
<ui:fragment rendered="#{not empty bean.uploadedFile}">
<img src="data:image/png;base64,#{bean.imageContentsAsBase64}" />
</ui:fragment>
public String getImageContentsAsBase64() {
return Base64.getEncoder().encodeToString(imageContents);
}
Note: I assume that Java 8 is available to you as java.util.Base64 was only introduced in that version. In case you're using an older Java version, use DatatypeConverter.printBase64Binary(imageContents) instead.
In case you happen to use JSF utility library OmniFaces, you can also just use its <o:graphicImage> component instead which is on contrary to <p:graphicImage> capable of directly referencing a byte[] and InputStream bean property and rendering a data URI.
<o:graphicImage value="#{bean.imageContents}" dataURI="true" rendered="#{not empty bean.imageContents}">
Is it possible?:
//...
local:MvxBind="Text Format('{0} {1}', Stock, #string/in_stock)"/>
//...
I want to construct a text value using my property from ViewModel and string resource from strings.xml, but the example above does not work.
AFAIK it is not directly possible to bind to an Android string.
Working with Xamarin and Mvx you should use resx files to support internationalization (i18n).
You can easily access the resx file from a binding using an indexer on your ViewModel:
public abstract class BaseViewModel : MvxViewModel
{
public string this[string key] => Strings.ResourceManager.GetString(key);
}
Then in your View you can use it like:
local:MvxBind="Text Format('{0} {1}', Stock, [InStock])"
There is another way to bind strings in resx files that is using the ResxLocalization plugin and even though it does not support Format yet you can workaround it (you can check this issue Feature request: Combine MvxLang with Format to keep track of this)
Basically, you create your Strings.resx file in your PCL/NetStandard/Shared project and register it:
Mvx.RegisterSingleton(new MvxResxTextProvider(Strings.ResourceManager));
Then in your base view model you need to implement this property so your views and viewmodels have access to i18n:
public IMvxLanguageBinder TextSource => new MvxLanguageBinder("", GetType().Name);
Finally in your view you can call it using:
local:MvxLang="Text InStock"
Pay attention that it is using MvxLang instead of MvxBind. BTW you can use both of them but if you use Text in MvxLang then don't use it in MvxBind because problems will arise.
Finally you can combine the plugin with the indexer to lower the coupling between the ViewModel and the resx files and workaround the support of Format in the binding like this (taken from the issue abovementioned):
public abstract class BaseViewModel : MvxViewModel
{
private IMvxTextProvider _textProvider;
public BaseViewModel(IMvxTextProvider textProvider)
{
_textProvider = textProvider;
}
public string this[string key] => _textProvider.GetText("", "", key);
}
and in your view (because of Format we cannot use MvxLang here):
local:MvxBind="Text Format('{0} {1}', Stock, [InStock])"
HIH
Windows phone 8 with Caliburn.Micro 2.0.1 cannot bind to LongListSelector. For Caliburn tries to bind items to Visibility property.
Here is XAML
<phone:LongListSelector
x:Name="Items"
ItemTemplate="{StaticResource MyItemTemplate}">
</phone:LongListSelector>
and view model property is pretty basic:
IObservableCollection<Item> _Items;
public IObservableCollection<Item> Items
{
get { return _Items; }
set
{
_Items = value;
NotifyOfPropertyChange(() => Items);
}
}
public class Item : PropertyChangedBase
{
string _Name;
public string Name
{
get { return _Name; }
set { _Name = value; NotifyOfPropertyChange(() => Name); }
}
}
Here is the debug output
System.Windows.Data Error: 'MS.Internal.Data.DynamicValueConverter' converter failed to convert value 'Caliburn.Micro.BindableCollection`1[Checklists.ViewModels.ItemsPageViewModel+Item]' (type 'Caliburn.Micro.BindableCollection`1[CLS.ViewModels.ItemsPageViewModel+Item]'); BindingExpression: Path='Items' DataItem='CLS.ViewModels.ItemsPageViewModel' (HashCode=38524289); target element is 'Microsoft.Phone.Controls.LongListSelector' (Name='Items'); target property is 'Visibility' (type 'System.Windows.Visibility').. System.InvalidOperationException: Can't convert type Caliburn.Micro.BindableCollection`1[CLS.ViewModels.ItemsPageViewModel+Item] to type System.Windows.Visibility.
at MS.Internal.Data.DefaultValueConverter.Create(Type sourceType, Type targetType, Boolean targetToSource)
at MS.Internal.Data.DynamicValueConverter.EnsureConverter(Type sourceType, Type targetType)
at MS.Internal.Data.DynamicValueConverter.Convert(Object value, Type targetType, Object parameter, CultureInfo culture)
at System.Windows.Data.BindingExpression.ConvertToTarget(Object value).
The convention you're trying to make use of here is the one Caliburn.Micro has set up for ItemsControl, unfortunately it doesn't appear that LongListSelector inherits from ItemsControl. It's odd that it doesn't so you'd assume everything would just work.
A very basic convention for LongListSelector could be added with the following
ConventionManager.AddElementConvention<LongListSelector>(LongListSelector.ItemsSourceProperty, "DataContext", "Loaded");
which would be called in your Bootstrapper. Note that this convention does't set up a default ItemTemplate that the one for ItemsSource does.
Edit:
The first property is used for property binding conventions, if you have a property matching the x:Name then this is the property bound to.
The second is the parameter property, if you refer to the element as a parameter in a message such as cm:Message.Attach="DoStuff(Items)" then what property is used.
The third is event that fires the action if there is one attached.
The one mentioned in the comments
ConventionManager.AddElementConvention<LongListSelector>(LongListSelector.Items‌​SourceProperty, "SelectedItem", "SelectionChanged");
is better in that if you're using any of the other features that require the second two properties. The first convention simply uses boiler plate parameters.
which makes sense its not a bug since LongListSelector isn't in the ConventionManager list of controls for windows Phone. You would have to add it as a custom convention for that control. Otherwise just bind normally...
I need to display a number as binary string (e.g. 8 => 1000). Sure I can convert it using BitConverter and set the text of my TextBox on my own in the code behind file. But this looks somewhat ugly. Is it possible to bind the TextBox to some source and convert it automatically?
I would suggest to use a ValueConverter
Create a class like this:
public class BinaryConverter : IValueConverter
{
public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return System.Convert.ToString(Convert.ToInt32(Convert.ToDouble(value)), 2);
}
public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
Then you can use it like this (without any code behind)
<Window.Resources>
<local:BinaryConverter x:Key="binConverter"></local:BinaryConverter>
</Window.Resources>
<StackPanel>
<Slider Name="sli" Minimum="0" Maximum="255" IsSnapToTickEnabled="True">
</Slider>
<TextBox Text="{Binding ElementName=sli,Path=Value,Mode=OneWay,Converter={StaticResource binConverter}}"></TextBox>
</StackPanel>
I have an ASP.NET 3.5 SP1 web application that uses a custom JavaScriptConverter. The code used to work at some time in the past, but has stopped working. I do not know what changes have happened in the middle server side. The problem we are seeing now is that the converter is not being invoked, so we are getting errors that System.Data.DataRow cannot be serialized.
The following is the relevant portion of web.config:
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization>
<converters>
<add name="DataSetConverter" type="Microsoft.Web.Preview.Script.Serialization.Converters.DataSetConverter, Microsoft.Web.Preview" />
<add name="DataRowConverter" type="WebUI.DataRowConverter, WebUI.DataRowConverter, Version=1.1.0.323, Culture=neutral" />
<add name="DataTableConverter" type="Microsoft.Web.Preview.Script.Serialization.Converters.DataTableConverter, Microsoft.Web.Preview" />
</converters>
</jsonSerialization>
</webServices>
</scripting>
</system.web.extensions>
A trimmed version of the class is as follows (trimmed only to avoid wasting space on unnecesary implementation):
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Web.Script.Serialization;
namespace WebUI {
public class DataRowConverter : JavaScriptConverter {
private ReadOnlyCollection<Type> _supportedTypes = new ReadOnlyCollection<Type>(new Type[] { typeof(DataRow) });
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) {
// stuff
return dr;
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) {
// stuff
return dictionary;
}
public override IEnumerable<Type> SupportedTypes {
get {
return this._supportedTypes;
}
}
}
}
What seems to happen is that the class is indeed being loaded (if we take it out of web.config and the project references, no breakpoints are available; put it back into web.config and copy the DLL/PDB by hand or add it to the project, breakpoints are available), but it's not being used propertly. No breakpoint anywhere in the class is hit, and no exceptions (including one thrown in a constructor added to see what happens) are thrown. It seems like the class is being loaded but never called.
This is on IIS 7.5 and IIS 7.0 in Integrated mode, if it matters.
Anyone have any ideas?
OK, just in case anyone else hits this, when calling web services through the automatically generated test pages, the custom serializers are not invoked - they are bypassed. This is apparently by design.