I'm trying to bind an xp:inputRichText to a bean (ChatBean), but get this validation error when the code tries update the field to the bean:
java.lang.IllegalArgumentException: argument type mismatch
I've tried a few of different things like converters to make sure the text will be a string, printing debug messages to find out where things go wrong, changed the type of the "setChatContent()" method (that sets the input to read-only), but can't get it to work.
Am I missing something, or is it not possible? Any thoughts?
The page:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:messages id="messages1"></xp:messages>
<xp:inputRichText id="inputRichText1" value="#{Chat.chatContent}"></xp:inputRichText>
<xp:button value="Save" id="button1" type="button">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete" save="false">
<xp:this.action>
<xp:actionGroup>
<xp:executeScript script="#{javascript:Chat.saveContent();}"></xp:executeScript>
<xp:openPage name="/chat.xsp"></xp:openPage>
</xp:actionGroup>
</xp:this.action>
</xp:eventHandler>
</xp:button>
The error occurs after I hit the "Save" button, which calls a method on the Chat bean (code is shortened):
public class ChatBean implements Serializable {
private static final long serialVersionUID = 1L;
private String chatContent;
public String getChatContent() {
return chatContent;
}
public void setChatContent(String chatContent) {
this.chatContent = chatContent;
}
public void saveContent() {
// TODO implement save
this.chatContent = "";
}
}
The UIInputRichText requires an object of type com.ibm.xsp.http.MimeMultipart
If you change your ChatBean to work with this instead, it should work as desired:
public class ChatBean implements Serializable {
private static final long serialVersionUID = 1L;
private com.ibm.xsp.http.MimeMultipart chatContent;
public com.ibm.xsp.http.MimeMultipart getChatContent() {
return chatContent;
}
public void setChatContent(com.ibm.xsp.http.MimeMultipart chatContent) {
this.chatContent = chatContent;
}
public void saveContent() {
// TODO implement save
this.chatContent = null;
}
}
Related
When creating a new class or method I used to be able to see the parameters needed. But, now they don't come up anymore. How do I view parameters when creating a class?
Running the latest windows version.
public class Main {
public static void main(String args[]) {
Case theCase = new Case("Default", "Corsair", "500W");
}
}
public class Case {
private String model;
private String manufacturer;
private String powerSupply;
public Case(String model, String manufacturer, String powerSupply,) {
this.model = model;
this.manufacturer = manufacturer;
this.powerSupply = powerSupply;
}
public void pressPowerButton() {
System.out.println("Power button pressed");
}
public String getModel() {
return model;
}
public String getManufacturer() {
return manufacturer;
}
public String getPowerSupply() {
return powerSupply;
}
}
When making theCase I can't see what my parameters are and have to move to the "Case" class back and forth
You can explicitly call Parameter Info action which is usually mapped to Ctrl/(Cmd) - p.
Nevermind in order to see the parameters as you type you must type them while in the editor without moving your cursor.
I am using Strings.resx, Strings.de.resx, etc. to localize Xamarin.Forms app.
I need to be able to change interface language at run time, and it (allmost) works.
Xamarin generates static class Strings in namespace MyProject.Resources from resource files, and I use those values to display strings on UI.
When doing it from code, it works flawlessly:
await DisplayAlert(Strings.lblConfirmDelete, Strings.lblDeleteMessage, Strings.lblOK, Strings.lblCancel));
Problem is - not all attributes defined this way from XAML are updated when I change UI culture during runtime.
Buttons, Labels, Entry properties (Placeholder etc.) change as they should, but PageTitle, Toolbaritems, and some other properties remain in previous language.
I presume that some of these are populated when Page is first created, and are not updated on culture (and UI culture) change.
So, basically, I need a way to combine {DynamicResource ...} with values from resources.
I know that DynamicResource is ment to be used with Resource dictionary, but that is not a good way to store language translations for localization.
I tried
Text="{DynamicResource {x:Static lr:Strings.lblAddNew}}"
also not working.
Is there a way of refreshing page dynamicaly?
I also tried calling
global::Xamarin.Forms.Xaml.Extensions.LoadFromXaml(this, typeof(MainListPage));
from Appearing event for that page, but that also does not work.
Any ideas?
Part of XAML file
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyProject.View"
xmlns:rs="clr-namespace:MMPI"
x:Class="MyProject.MainListPage"
xmlns:lr="clr-namespace:MyProject.Resources"
Title="{x:Static lr:Strings.appName}"
>
<ContentPage.ToolbarItems>
<ToolbarItem
Name="New"
Order="Primary"
Priority="0"
Text="{x:Static lr:Strings.lblAddNew}"
Clicked="New_Clicked"
>
When i encountered that challenge in a project I resolved it by using a simple class ResourceLoader and making use of INotifyPropertyChanged.
You can access the Instanceproperty from anywhere and change the culture. All String that are bound to the index would update.
The ResourceManager instance injected into the constructor must be set up appropriately.
public class ResourceLoader : INotifyPropertyChanged
{
private readonly ResourceManager manager;
private CultureInfo cultureInfo;
public ResourceLoader(ResourceManager resourceManager)
{
this.manager = resourceManager;
Instance = this;
this.cultureInfo = CultureInfo.CurrentUICulture;
}
public static ResourceLoader Instance { get; private set; }
public string GetString(string resourceName)
{
string stringRes = this.manager.GetString(resourceName, this.cultureInfo);
return stringRes;
}
public string this[string key] => this.GetString(key);
public void SetCultureInfo(CultureInfo cultureInfo)
{
this.cultureInfo = cultureInfo;
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(null));
}
public event PropertyChangedEventHandler PropertyChanged;
}
To display the localized strings in your application you need to bind through the indexer like so:
<Label Text="{Binding [Test], Source={x:Static ResourceLoader.Instance}}" />
Since it is now bound it should update when you call ResourceLoader.SetCultureInfo because the Item[] 'PropertyName' is causing bound controls to re-fetch the values to their bound keys.
Update
I just tested it if i was talking bogus and for some reason the property changed didn't work. I've added a different approach below, which is close to what i'm using in production i urge you to add some kind of weak reference 'caching' instead of the simple list holding all the string resources (otherwise they will be kept forever)
I'm keeping above for reference.
public class ResourceLoader
{
public ResourceLoader(ResourceManager resourceManager)
{
this.manager = resourceManager;
Instance = this;
this.cultureInfo = CultureInfo.CurrentUICulture;
}
private readonly ResourceManager manager;
private CultureInfo cultureInfo;
private readonly List<StringResource> resources = new List<StringResource>();
public static ResourceLoader Instance { get; private set; }
public StringResource this[string key] {
get { return this.GetString(key); }
}
public StringResource GetString(string resourceName)
{
string stringRes = this.manager.GetString(resourceName, this.cultureInfo);
var stringResource = new StringResource(resourceName, stringRes);
this.resources.Add(stringResource);
return stringResource;
}
public void SetCultureInfo(CultureInfo cultureInfo)
{
this.cultureInfo = cultureInfo;
foreach (StringResource stringResource in this.resources) {
stringResource.Value = this.manager.GetString(stringResource.Key, cultureInfo);
}
}
}
StringResource:
public class StringResource : INotifyPropertyChanged
{
public StringResource(string key, string value)
{
this.Key = key;
this.Value = value;
}
private string value;
public string Key { get; }
public string Value {
get { return this.value; }
set {
this.value = value;
this.OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
XAML Binding
<Label Text="{Binding [ResourceKey].Value, Mode=OneWay, Source={x:Static local:ResourceLoader.Instance}}"
/>
Update 2
Came across this link where they implemented it similarly to my first approach. Maybe you can give it a try.
Update 3
Fixed the first approach. Both are working now. What was needed was this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(null)); instead of this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(Item[]));
I solved it very similar to #woelliJ . I just wanted to have key as strongly types from static class and binding should be in code behind.
ITranslationService is singleton from static variable. It is very close like #woelliJ .
[ContentProperty("Text")]
public sealed class TranslateExtension : IMarkupExtension<BindingBase>
{
private readonly ITranslationService? _translationService;
public TranslateExtension()
{
_translationService = Mobile.App.TranslationService;
}
public string? Text { get; set; }
public BindingBase ProvideValue(IServiceProvider serviceProvider)
{
var translationItem = _translationService[Text];
var binding = new Binding
{
Mode = BindingMode.OneWay,
Path = $"Value",
Source = translationItem,
};
return binding;
}
object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
{
return (this as IMarkupExtension<BindingBase>).ProvideValue(serviceProvider);
}
}
[AddINotifyPropertyChangedInterface]
public class TranslationItem
{
public string? Key { get; set; }
public string? Value { get; set; }
}
Then label would be like this
<Label FontSize="Title" Text="{services:Translate Text={x:Static models:M.AboutTestInfoTitle}}" />
The problem I have involves a pretty complex class structure but I managed to summarize the gist of it in the following simpler example. I need to be able to serialize an object of class MyItem (including private property 'text') and subsequently deserialize it without having a parameter-less constructor available and without being able to create one because it would totally mess up the current logic.
class MyCollection:
#XmlRootElement(name="collection")
public class MyCollection {
public MyCollection() {
this.items = new ArrayList<MyItem>();
}
#XmlElement(name="item")
private List<MyItem> items;
public void addItem(String text) {
this.items.add(new MyItem(text));
}
}
class MyItem:
public class MyItem {
public MyItem(String text) {
this.text = text;
}
#XmlAttribute
private String text;
}
The first requirement (serialize MyItem including private property) is met out of the box and I get the following xml as a result:
<collection>
<item text="FIRST"/>
<item text="SECOND"/>
<item text="THIRD"/>
</collection>
In order to meet the second requirement I decorated class MyItem with attribute #XmlJavaTypeAdapter
#XmlJavaTypeAdapter(MyItemAdapter.class)
public class MyItem {
...
and introduced classes AdaptedMyItem
public class AdaptedMyItem {
private String text;
public void setText(String text) { this.text = text; }
#XmlAttribute
public String getText() { return this.text; }
}
and MyItemAdapter
public class MyItemAdapter extends XmlAdapter<AdaptedMyItem, MyItem> {
#Override
public MyItem unmarshal(AdaptedMyItem adaptedMyItem) throws Exception {
return new MyItem(adaptedMyItem.getText());
}
#Override
public AdaptedMyItem marshal(MyItem item) throws Exception {
AdaptedMyItem result = new AdaptedMyItem();
result.setText("???"); // CANNOT USE item.getText()
return result;
}
}
but this is where I get stuck because in method marshal I cannot access MyItem.text and so I cannot use the standard approach for dealing with immutable classes in JAXB.
Bottomline: I would like to use the class adapter mechanism only when deserializing (because I need to invoke a non-parameterless constructor) but not when serializing (because I cannot access private properties). Would that be possible?
I'm working with Xamarin Android on Xamarin Studio 5.5.3, Im trying to create a global session state using the sample on this link:
Login Session - Activities
My code is pretty similar as the one on the link.
My Application Class:
namespace MyApp.Library.Droid
{
public class SessionApplication : Application
{
private static int _userID;
private static string _email;
private static string _firstName;
private static string _lastName;
public override void OnCreate() {
base.OnCreate();
_userID=0;
_email=null;
_firstName = null;
_lastName = null;
}
public static int UserID
{
get { retu`enter code here`rn _userID; }
set { _userID=value; }
}
public static string Email
{
get { return _email; }
set { _email=value; }
}
public static string FirstName
{
get { return _firstName; }
set { _firstName=value; }
}
public static string LastName
{
get { return _lastName; }
set { _lastName=value; }
}
}
}
My Android Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0"
package="myapp.ui.droid">
<uses-sdk />
<application android:label="myapp.ui.droid" android:name="myapp.library.droid.SessionApplication">
</application>
</manifest>
my code compiles but then it runs throws this exception.
[MonoDroid] UNHANDLED EXCEPTION:
[MonoDroid] System.NotSupportedException: Unable to activate instance of type MyApp.Library.Droid.SessionApplication from native handle a2600019 --->
System.MissingMethodException: No constructor found for MyApp.Library.Droid.SessionApplication::.ctor(System.IntPtr, Android.Runtime.JniHandleOwnership) --->
Java.Interop.JavaLocationException: Exception of type 'Java.Interop.JavaLocationException' was thrown.
I'll appreciate your help.
Congratulations, you've found one of the few cases where you need to provide an explicit constructor that handles when a Java object is exposed to managed (Mono) code.
From the docs:
There are two scenarios in which the (IntPtr, JniHandleOwnership) constructor must be manually provided on a Managed Callable Wrapper subclass:
1 - Android.App.Application is subclassed. Application is special; the default Applicaton constructor will never be invoked, and the (IntPtr, JniHandleOwnership) constructor must instead be provided .
Virtual method invocation from a base class constructor.
To fix this, provide a constructor with the (IntPtr handle, JniHandleOwnership transfer) signature.
[Application]
public class SessionApplication : Application
{
public SessionApplication(IntPtr javaReference, JniHandleOwnership transfer)
:base(javaReference, transfer)
{
}
// ...
}
Some background reading:
Android Callable Wrappers
Xamarin.Android Architecture (See Java Activation specifically).
I'm trying to instance an object(s) from xaml. The object's class inherits from a base class. Everything works good except that the a base class property ("Key") is not setting correctly from xaml. It's always null. The object's properties itself are set OK from xaml. Also when I set the Key property from code it sets fine.
I put a breakpoint on the closing bracket of the MainWindow method to view the object data. The hover details tells me the Key property is always null.
Any ideas what I'm doing wrong?
<?xml version="1.0" encoding="utf-8" ?>
<GroupUiItem xmlns="clr-namespace:Configurator.UiCore"
Key="key_grp1" UserName="grp1">
<ParameterUiItem Key="key_par1" UserName="par1"/>
<GroupUiItem Key="key_grp2" UserName="grp2">
<ParameterUiItem Key="key_par2" UserName="par2"/>
<ParameterUiItem Key="key_par3" UserName="par3"/>
</GroupUiItem>
<ParameterUiItem Key="key_par4" UserName="par4"/>
<ParameterUiItem Key="key_par5" UserName="par5"/>
<ParameterUiItem Key="key_par6" UserName="par6"/>
</GroupUiItem>
public partial class MainWindow : Window
{
public MainWindow()
{
GroupUiItem ConfigUi = new GroupUiItem();
InitializeComponent();
using (FileStream stream = new FileStream("XMLFile1.xaml", FileMode.Open, FileAccess.Read))
{
ConfigUi = XamlReader.Load(stream) as GroupUiItem;
}
ConfigUi.Key = "key_grp1"; // this works OK
CategoryList.ItemsSource = ConfigUi.Children;
}
}
// These are in the Configurator.UiCore namespace:
public class ConfiguratorUiItem
{
protected string _Key;
public string Key
{
get { return _Key; }
set { _Key = value; }
}
}
[ContentProperty("Children")]
public class GroupUiItem : ConfiguratorUiItem
{
private ObservableCollection<ConfiguratorUiItem> _Children = new ObservableCollection<ConfiguratorUiItem>();
public ObservableCollection<ConfiguratorUiItem> Children
{ get { return _Children; }
set { _Children = value; }
}
private string _UserName;
public string UserName
{ get { return _UserName; }
set { _UserName = value; }
}
}
public class ParameterUiItem : ConfiguratorUiItem
{
private string _ParameterType;
public string ParameterType
{
get { return _ParameterType; }
set { _ParameterType = value; }
}
private string _UserName;
public string UserName
{
get { return _UserName; }
set { _UserName = value; }
}
}
OK figured out my problem. Noob mistake. Needed to set build action to None and copy always. I had build action set to a page so it wasn't a loose xaml and wasn't updating to appropriate folder. I copied the xaml file to output directory manually when I first couldn't figure out the problem. This caused the program to always use the old file.
When I did this also had to add ";assembly=Configurator" to the end of the xmlns so that it now reads: "xmlns="clr-namespace:Configurator.UiCore;assembly=Configurator". Then it worked.