My modelView:
public string Status {
get { return _status; }
set {
if (value == _status) {
return;
}
_status = value;
OnPropertyChanged ("Status");
}
My View:
Label labelStatus = new Label {
TextColor = Color.Green,
FontSize = 20d
};
labelStatus.SetBinding (Label.TextProperty, "Status");
Then I want to present the status using something like:
string presentStatus = string.Format("Your status is {0}...", labelStatus);
Label yourStatus = new Label{Text=presentStatus}
But that doesn't really work. Nor does using
string presentStatus = string.Format("Your status is {0}...", SetBinding(Label.TextProperty,"Status"));
So how should I do to add my bound values with more text before presenting them for the user in a view.
If using XAML (which i don't), it seems possible according to: http://developer.xamarin.com/guides/cross-platform/xamarin-forms/xaml-for-xamarin-forms/data_binding_basics/
Xamarin Forms binding implementation doesn't currently allow complex binding scenarios like embedding bound text within static text.
There are two options
a. use multiple labels - one with the static text, one with the bound text
b. use a property on your ViewModel that concatenates the text for you
public string StatusText
{
get
{
return string.Format("Your status is {0}...", Status);
}
}
public string Status {
get { return _status; }
set {
if (value == _status) {
return;
}
_status = value;
OnPropertyChanged ("Status");
OnPropertyChanged ("StatusText");
}
You can do that in the BindingContextChanged-event:
labelStatus.BindingContextChanged += (sender, e) =>
{
// Here you can change the Text dynamically
// E.G. labelStatus.text = "Title: " + labelStatus.text
};
Related
Intro
I'm working on an application and I want to be able to change the language when the app is running. For cross-platform compatibility I'm using AvaloniaUI.
I've found a few helpful articles:
Simple localization in WPF
Simple localization in WPF, extended for multiple resource-files
Answer to question on StackOverflow (basically the first link)
The problem
On startup of the app a binding is created (in LocExtensionWithMultipleResxFiles) between my control on the view and string this[string key] ( in TranslationSourceWithMultipleResxFiles). The app correctly loads the translations on startup.
On my View I have a button, the ClickEvent correctly sets TranslationSourceWithMultipleResxFiles.Instance.CurrentCulture but the text in my view doesn't update. I'm not sure where I did something wrong or if I need to change the code somewhere, so any help is appreciated.
My code
Using the above articles I have the following code:
TranslationSourceWithMultipleResxFiles contains a Dictionary for all the ResourceManagers that are used. string this[string key] returns the translated text. CurrentCulture is the property you set to change the Culture.
public class TranslationSourceWithMultipleResxFiles : INotifyPropertyChanged
{
public static TranslationSourceWithMultipleResxFiles Instance { get; } = new TranslationSourceWithMultipleResxFiles();
private readonly Dictionary<string, ResourceManager> resourceManagerDictionary = new Dictionary<string, ResourceManager>();
// key is the baseName + stringName that is binded to, this returns the translated text.
public string this[string key]
{
get
{
var (baseName, stringName) = SplitName(key);
string? translation = null;
if (resourceManagerDictionary.ContainsKey(baseName))
translation = resourceManagerDictionary[baseName].GetString(stringName, currentCulture);
return translation ?? key;
}
}
// the culture TranslationSourceWithMultipleResxFiles uses for translations.
private CultureInfo currentCulture = CultureInfo.InstalledUICulture;
public CultureInfo CurrentCulture
{
get { return currentCulture; }
set
{
if (currentCulture != value)
{
currentCulture = value;
NotifyPropertyChanged(string.Empty); // string.Empty/null indicates that all properties have changed
}
}
}
// WPF bindings register PropertyChanged event if the object supports it and update themselves when it is raised
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public void AddResourceManager(ResourceManager resourceManager)
{
if (!resourceManagerDictionary.ContainsKey(resourceManager.BaseName))
resourceManagerDictionary.Add(resourceManager.BaseName, resourceManager);
}
public static (string baseName, string stringName) SplitName(string name)
{
int idx = name.LastIndexOf('.');
return (name.Substring(0, idx), name.Substring(idx + 1));
}
}
In xaml you set the Translation.ResourceManager per UserContorl/Window etc. This is used so multiple resource files can be used in the application. Each child Control looks to this ResourceManager for their translations.
public class Translation : AvaloniaObject
{
public static readonly AttachedProperty<ResourceManager> ResourceManagerProperty = AvaloniaProperty.RegisterAttached<Translation, AvaloniaObject, ResourceManager>("ResourceManager");
public static ResourceManager GetResourceManager(AvaloniaObject dependencyObject)
{
return (ResourceManager)dependencyObject.GetValue(ResourceManagerProperty);
}
public static void SetResourceManager(AvaloniaObject dependencyObject, ResourceManager value)
{
dependencyObject.SetValue(ResourceManagerProperty, value);
}
}
Creates a Binding between the Control on the view and the correct ResourceManager.
public class LocExtensionWithMultipleResxFiles : MarkupExtension
{
public string StringName { get; } // Key name of the translation in a resource file.
public LocExtensionWithMultipleResxFiles(string stringName)
{
StringName = stringName;
}
// Find out what ResourceManager this control uses
private ResourceManager? GetResourceManager(object control)
{
if (control is AvaloniaObject dependencyObject)
{
object localValue = dependencyObject.GetValue(Translation.ResourceManagerProperty);
if (localValue != AvaloniaProperty.UnsetValue)
{
if (localValue is ResourceManager resourceManager)
{
TranslationSourceWithMultipleResxFiles.Instance.AddResourceManager(resourceManager);
return resourceManager;
}
}
}
return null;
}
// Create a binding between the Control and the translated text in a resource file.
public override object ProvideValue(IServiceProvider serviceProvider)
{
object? targetObject = (serviceProvider as IProvideValueTarget)?.TargetObject;
if (targetObject?.GetType().Name == "SharedDp") // is extension used in a control template?
return targetObject; // required for template re-binding
string baseName = GetResourceManager(targetObject)?.BaseName ?? string.Empty; // if the targetObject has a ResourceManager set, BaseName is set
if (string.IsNullOrEmpty(baseName)) // if the targetobjest doesnt have a RM set, it gets the root elements RM.
{
// rootObject is the root control of the visual tree (the top parent of targetObject)
object? rootObject = (serviceProvider as IRootObjectProvider)?.RootObject;
baseName = GetResourceManager(rootObject)?.BaseName ?? string.Empty;
}
if (string.IsNullOrEmpty(baseName)) // template re-binding
{
if (targetObject is Control frameworkElement)
baseName = GetResourceManager(frameworkElement.TemplatedParent)?.BaseName ?? string.Empty;
}
// create a binding between the Control and the correct resource-file
var binding = new ReflectionBindingExtension
{
Mode = BindingMode.OneWay,
Path = $"[{baseName}.{StringName}]", // This is the ResourceManager.Key
Source = TranslationSourceWithMultipleResxFiles.Instance,
FallbackValue = "Fallback, can't set translation.",
TargetNullValue = StringName,
};
return binding.ProvideValue(serviceProvider);
}
}
My View
<Window <!-- Standard Window xaml -->
xmlns:l="clr-namespace:TestAppForMVVMwithBaseClasses.Localization"
l:Translation.ResourceManager="{x:Static p:Resources.ResourceManager}">
<StackPanel>
<TextBlock Text="{l:LocExtensionWithMultipleResxFiles String1}"/>
<Button Content="Nl" Click="CurrentCultureNl_Click"/>
<Button Content="En" Click="CurrentCultureEn_Click"/>
</StackPanel>
</Window>
I could not find any column to set background image inside SearchManager class.
When Google Play app's search result is selected, a background image is displayed but I don't seem to find any public api/column to set it.
Here is my code for content provider's query method
Any idea guys?
Device: Nexus player
#Nullable
#Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
final String searchKey = (selectionArgs == null) ? "" : selectionArgs[0];
if (!TextUtils.isEmpty(searchKey)) {
// Get title list from search query
ArrayList<TitleSimpleInfo> searchedTitleList = searchTitlesWithKeyword(searchKey);
// return null cursor if no data found
if (searchedTitleList == null || searchedTitleList.isEmpty()) {
return null;
}
// prepare cursor
MatrixCursor matrixCursor = new MatrixCursor(new String[]{
SearchManager.SUGGEST_COLUMN_TEXT_1,
SearchManager.SUGGEST_COLUMN_TEXT_2,
SearchManager.SUGGEST_COLUMN_CONTENT_TYPE,
SearchManager.SUGGEST_COLUMN_INTENT_ACTION,
SearchManager.SUGGEST_COLUMN_INTENT_DATA,
SearchManager.SUGGEST_COLUMN_RESULT_CARD_IMAGE,
});
// add search result to cursor
for (TitleSimpleInfo title : searchedTitleList) {
matrixCursor.addRow(new Object[]{
title.getTitleName(),
title.getTitleCatch(),
SEARCH_CONTENT_TYPE,
Intent.ACTION_SEARCH,
SEARCH_INTENT_DATA + title.getTitleCode(),
SEARCH_IMAGE_HEADER + title.getThumbnailUrl(),
});
}
return matrixCursor;
} else {
return null;
}
}
in my application i have a Custom text box with BasicEditField.FILTER_NUMERIC. When the user enter the value in the field the comma should be added to the Currency format .
EX:1,234,567,8.... like this.
In my code i tried like this.
protected boolean keyUp(int keycode, int time) {
String entireText = getText();
if (!entireText.equals(new String(""))) {
double val = Double.parseDouble(entireText);
String txt = Utile.formatNumber(val, 3, ",");// this will give the //comma separation format
setText(txt);// set the value in the text box
}
return super.keyUp(keycode, time);
}
it will give the correct number format... when i set the value in the text box it will through the IllegalArgumentException. I know BasicEditField.FILTER_NUMERIC will not allow the charector like comma(,)..
How can i achieve this?
I tried this way and it works fine...
public class MyTextfilter extends TextFilter {
private static TextFilter _tf = TextFilter.get(TextFilter.REAL_NUMERIC);
public char convert(char character, int status) {
char c = 0;
c = _tf.convert(character, status);
if (c != 0) {
return c;
}
return 0;
}
public boolean validate(char character) {
if (character == Characters.COMMA) {
return true;
}
boolean b = _tf.validate(character);
if (b) {
return true;
}
return false;
}
}
and call like this
editField.setFilter(new MyTextfilter());
I have a table with 2 columns: a checkbox and a textfield. I want to disable the textfield depending of the respective (same row) checkbox status. If the checkbox is checked then the textfield will be cleared and be read only. Is this possible ? Here is my code:
#SuppressWarnings("serial")
private Table filtersTable() {
final Table table = new Table();
table.setPageLength(10);
table.setSelectable(false);
table.setImmediate(true);
table.setSizeFull();
// table.setMultiSelectMode(MultiSelectMode.SIMPLE) ;
table.addContainerProperty("Tipo filtro", CheckBox.class, null);
table.addContainerProperty("Valor", String.class, null);
table.setEditable(true);
for (int i = 0; i < 15; i++) {
TextField t = new TextField();
t.setData(i);
t.setMaxLength(50);
t.setValue("valor " + i);
t.setImmediate(true);
t.setWidth(30, UNITS_PERCENTAGE);
CheckBox c = new CheckBox(" filtro " + i);
c.setWidth(30, UNITS_PERCENTAGE);
c.setData(i);
c.setImmediate(true);
c.addListener(new ValueChangeListener() {
#Override
public void valueChange(ValueChangeEvent event) {
// within this, could I access the respective row ID
// (i) then enable/disable TextField t on second column ?
System.out.println("event.getProperty().getValue()="
+ event.getProperty().getValue());
}
});
table.addItem(new Object[] { c, t }, i);
}
return table;
}
Thanks
Few changes to your code made it possible.
Not the finiest way, but te simpliest.
First,you have to set your second column (Valor) to TextField.class not String.class.
Here the change :
table.addContainerProperty("Valor", TextField.class, null);
Instead of keepin the variable i in the CheckBox.setData(), I suggest you to link your checkBox to the TextField of the same row, like this :
c.setData(t);
Finally I made little change to your listener :
c.addListener(new Property.ValueChangeListener() {
public void valueChange(ValueChangeEvent event) {
CheckBox checkBox = (CheckBox)event.getProperty();
if((Boolean) checkBox.getValue())
{
TextField associatedTextField = (TextField)checkBox.getData();
//Do all your stuff with the TextField
associatedTextField.setReadOnly(true);
}
}
});
Hope it's work for you!
Regards, Éric
public class MyCheckBox extends CheckBox {
private TextBox t;
public MyCheckBox(TextBox t) {
this.t = t;
attachLsnr();
}
private void attachLsnr()
{
addListener(new Property.ValueChangeListener() {
public void valueChange(ValueChangeEvent event) {
CheckBox checkBox = (CheckBox)event.getProperty();
if((Boolean) checkBox.getValue())
{
t.setReadOnly(true);
}
}
});
}
}
I have created Table using vaadin.Now i want to set font size for particular column content in that table.Is it possible to set font size for particular column in that table?.
If so please give me idea to set the font size.If u can provide me some code snippet.
Yes, with CellStyleGenarators. Check 5.12.2 in the Book of Vaadin. You basically do a
if(propertyId.equals(yourColumnName)) {
return "someStyleName";
}
else {
return null;
}
inside your Table.CellStyleGenerator() and set the style for your text in css.
using CellStyleGenerator
simpleTable.setCellStyleGenerator(new Table.CellStyleGenerator() {
#Override
public String getStyle(Table components, Object itemId, Object columnId) {
int row = Integer.valueOf((String)itemId);
if (row%2 == 0)
return "grey";
else
return "white";
}
});
ColumnGenerator as it is described in How to get started with Vaadin: Table Styling
public class DescriptionColumnGenerator implements
Table.ColumnGenerator {
#Override
public Object generateCell(Table components, Object itemId, Object columnId) {
int row = Integer.valueOf((String)itemId);
Property prop = components.getItem(itemId).getItemProperty(columnId);
Label label = new Label("desc: " + prop.getValue());
if (row%2 != 0) {
label.addStyleName("column-description");
label.addStyleName("column-" + (String) columnId);
}
return label;
} }
You can add a style name for this column.