DatePicker selects selections even if binded property has not been set - xamarin.forms

I got my DatePicker. I check if new comming date is equal or greater than SelectedOrder.TargetDate.Date.
The check itself is fine and not allow if coindition is not match, nevertheless what user selects on calendar it stay in calendar. Why calendar sets user's selection even if SelectedTargetDate was not changed?
<DatePicker Date="{Binding SelectedTargetDate, Mode=TwoWay}"/>
public DateTime SelectedTargetDate
{
get => _selectedTargetDate;
set
{
if (SelectedOrder == null) return; //on program run first time it's null
if (value.Date < SelectedOrder.TargetDate.Date)
_pageService.DisplayAlert("Ostrzeżenie", "New date cannot be older than TargetDate", "ok", "cancel");
else
SetValue(ref _selectedTargetDate, value);
}
}

I don't know if I understand you correctly, do you want to keep the SelectedOrder.TargetDate if the condition is not satisfied ?
If yes,you could let your model implement INotifyPropertyChanged and change like below:
public class YourModel: INotifyPropertyChanged
{
...
public event PropertyChangedEventHandler PropertyChanged;
public DateTime SelectedTargetDate
{
get => _selectedTargetDate;
set
{
if (SelectedOrder == null) return; //on program run first time it's null
if (value.Date < SelectedOrder.Date)
{
_pageService.DisplayAlert("Ostrzeżenie", "New date cannot be older than TargetDate", "ok", "cancel");
}
else
{
_selectedTargetDate = value;
}
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedTargetDate"));
}
}
}

Related

Xamarin Forms: Propertychanged is not triggered when refreshing from database

I'm having an object in my viewmodel which consists of an Id and some other attributes.
my equality check contains the check on Id, so I can identify items in lists when refreshing.
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
return Equals(obj as Class);
}
public bool Equals(Class other)
{
if (other == null)
{
return false;
}
return this.Id.Equals(other.Id);
}
Now when I'm on a detailPage which is only having one item, I want to manually refresh that item from the database.
When doing my refresh the Id obviously does not change, but the remaining attributes can.
Now the problem I have is that the Propertychanged is not triggered when item is identical(based on id).
Class refreshedItem = await Task.Run(() => backendConnection.GetSchedule(scheduleId, DTOType.Maxi, BackEndSettings.Default.SystemOfMeasurement));
Item = refreshedItem;
If I set the Item to a dummy item in between it is triggered every time.
Class refreshedItem = await Task.Run(() => backendConnection.GetSchedule(scheduleId, DTOType.Maxi, BackEndSettings.Default.SystemOfMeasurement));
Item = new Class(Guid.Empty) { Title = "test" };
Item = refreshedItem;
Looking at Github Fody Properties Overview, the (default) code that is injected in Item setter is equivalent to
if (value != item)
OnPropertyChanged();
It only fires when not equal.
The documentation for Fody Properties says to use Attributes to control its behavior. For what you want, use DoNotCheckEqualityAttribute.

Setting control Enabled property in SelectedIndexChanged() only works first time it is run

I have a dropdown and I want to change another controls Enabled property when a certain value is chosen, e.g
private void ddlTest_SelectedIndexChanged()
{
if (ddlTest.Value == "1")
{
TextBox1.Enabled = false;
}
else
{
TextBox1.Enabled = true;
}
}
This works the first time it is run but never again after that - am I missing something?

Xamarin.Forms activate/deactivate toolbar items not working

I have a Xamarin.Form MainPage:ContentPage with a ToolbarItems Bar on top. The toolbar items are bound to my ViewModel like so:
<ToolbarItem Text="Sync" Command="{Binding ReloadCommand}" >
</ToolbarItem>
The availability of the Item depends on some logic:
private bool canReloadExecute(object arg)
{
bool result = (!IsReloading && (App.GetPersistentSetting("DeviceID") != "") && (App.GetPersistentSetting("BuildingID") != ""));
return result;
}
There is a separate dialog controlling the DeviceID and BuildingID on a different settings page. Once any of those ids is entered it is persistently stored away
App.SetPersistentSetting("DeviceID",value);
Problem is, that the menu items don't change their appearance once my code uses popAsync() to return to the Main page. I need to restart my app to see the changes. According to the debugger, canReloadExecute isn't called. Why this?
What I tried to work around this issue is to force a refresh in the MainPage's OnAppearing method like this:
public void RefreshToolbarItems()
{
TestApp.ViewModels.MainViewModel mvm = (TestApp.ViewModels.MainViewModel)BindingContext;
mvm.RefreshToolbarItems();
}
... and in the ViewModel:
public void RefreshToolbarItems()
{
OnPropertyChanged("BuildingScanCommand");
OnPropertyChanged("ReloadCommand");
}
but this code runs through but changes nothing, while the Debugger shows that the routine is indeed firing the events, they seem to go nowhere.
Any ideas how I can get my menu going?
Edit 1: "Show command initalization"
I am not shre what specifically you mean, but here is the whole code dealing with the command:
private ICommand _reloadCommand;
public ICommand ReloadCommand => _reloadCommand ?? (_reloadCommand = new Command(ExecuteReloadCommand, canReloadExecute));
private bool _isReloading = false;
public bool IsReloading
{
get => _isReloading;
set
{
_isReloading = value;
((Command)_reloadCommand).ChangeCanExecute();
OnPropertyChanged(nameof(ReloadCommand));
}
}
private bool canReloadExecute(object arg)
{
bool result = (!IsReloading && (App.GetPersistentSetting("DeviceID") != "") && (App.GetPersistentSetting("BuildingID") != ""));
return result;
}
private async void ExecuteReloadCommand(object obj)
{
IsReloading = true;
// Some code ...
IsReloading = false;
}
The goal is to disable the command, if either the command handler is already running, or if the configuration of DeviceID and/or BuildingId hasn't been done yet.
The enable/disable does almost work, if I set the DeviceId and BuildingId, and restart the app, the command is properly enabled or disabled. It doesn't work, however, if I set the Ids in a sub-page and return to the main page.
meanwhile I came to the conclusion, that firing onPropertyChange obviously doesn't make the command check its canReloadExecute. So the question is, how do I trigger this?
I finally solved the issue myself, this code works nicely for me:
public void RefreshToolbarItems()
{
((Command)BuildingScanCommand).ChangeCanExecute();
((Command)ReloadCommand).ChangeCanExecute();
}

TestFx - How to test javaFx MenuItems

Since MenuItem is not a Node, I'm not able to look it up. How do I test, if some MenuItem is disabled?
I've tried to look it up as it was a node and it returned me something, which looks like this..
(toString representation of returned object):
(ContextMenuContent$MenuItemContainer[id=mnEditHrom, styleClass=menu-item])
But i can't cast MenuItem on that, it says "Node cannot be converted to MenuItem" and when I call isDisabled() function on what was returned, i get incorrect information.
Lets say I have MenuItem with "mnEdit" id, which is disabled. When i call
find("#mnEdit").isDisabled();
it returns false. Find method looks like this:
public <T extends Node> T find(String query)
{
return (T) lookup(query).queryAll().iterator().next();
}
So again, how do I test whether some MenuItem is disabled or not in testFx?
You almost done in the original post. When you get the MenuItemContainer get the MenuItem firstly and finally call isDisable():
ContextMenuContent.MenuItemContainer actualMenuItemContainer = find("#mnEdit");
boolean actualResult = actualMenuItemContainer.getItem().isDisable();
I solved it by looking up MenuBar, identifying item I want to test by its Id and since I have now MenuItem obejct in hands, I can call isDisable() on it.
MenuTest.class
CommonTests common = new CommmonTests();
#Test
public void disabledMenuItemTest()
{
common.disabledMenuItemTest("#mainMenu", "mnEditHrom", true);
}
CommonTests.class
TestUtils utils = new TestUtils();
public void disabledMenuItemTest(String menuBarSelector, String menuItemId, boolean expected)
{
Boolean actual = utils.isMenuItemDisabled(menuBarSelector, menuItemId);
if (actual != null)
assertEquals("MenuItem "+menuItemId+" je enabled/disabled (expected = "+expected+").", expected, actual.booleanValue());
else
fail("MenuBar/MenuItem not found.");
}
TestUtils.class
public Boolean isMenuItemDisabled(String menuBarSelector, String menuItemId)
{
ArrayList<MenuItem> list = getAllMenuItems(menuBarSelector);
Boolean disabled = null;
if(list != null)
{
for(MenuItem item : list)
{
if(item.getId() != null && item.getId().equals(menuItemId))
return item.isDisable();
}
}
return disabled;
}
private ArrayList<MenuItem> getAllMenuItems(String menuBarSelector)
{
ArrayList<MenuItem> itemsList = new ArrayList<MenuItem>();
MenuBar menuBar = (MenuBar) find(menuBarSelector);
if(menuBar != null)
{
menuBar.getMenus().forEach(menu -> {
menu.getItems().forEach(menuItem -> {
itemsList.add(menuItem);
});
});
return itemsList;
}
return null;
}

Put and Get Selected Radio Button from Radio Group using SharedPreferences

want to store selected radio from and radio group and once that fragment is again launch , previous selected radio should be selected , I tried but not able to get it .
I need to store selected position on Click of button only .
This is code which I am using :
radiogender=(RadioGroup)rootView.findViewById(R.id.radioGroup1);
radiogender.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
// find which radio button is selected
if(checkedId == R.id.radioButton1) {
Toast.makeText(getActivity(), "You: Dude !!!",
Toast.LENGTH_SHORT).show();
} else if(checkedId == R.id.radioButton2) {
Toast.makeText(getActivity(), "You: Babe !!!",
Toast.LENGTH_SHORT).show();
}
}
});
Try something like this
radiogender=(RadioGroup)rootView.findViewById(R.id.radioGroup1);
radioButton1=(RadioButton) rootView.findViewById(R.id.radioButton1);
radioButton2=(RadioButton) rootView.findViewById(R.id.radioButton2);
SharedPreferences myPrefs=context.getSharedPreferences("general",context.MODE_PRIVATE); //you can give any name in place of general to your preferences
radiogender.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
// find which radio button is selected
if(checkedId == R.id.radioButton1) {
Toast.makeText(getActivity(), "You: Dude !!!",
Toast.LENGTH_SHORT).show();
//save in preferences
myPrefs.edit().putInt("selected",1).commint();
} else if(checkedId == R.id.radioButton2) {
Toast.makeText(getActivity(), "You: Babe !!!",
Toast.LENGTH_SHORT).show();
//save in preferences
myPrefs.edit().putInt("selected",2).commit();
}
}
});
//check if there is any value in preferences and set accordingly
int s=myPrefs.getInt("selected",0); //will return 0 when nothing is stored
if(s==1){
radioButton1.setChecked(true);
} else if(s==2){
radioButton2.setChecked(true);
}
To add a value in preferences, you first use the edit() tag and then use putInt or putString ,etc. to add value to the preferences.
Example putInt("selected",1 ); Here the 'selected' is the key or name that you provide so that you can fetch the value with that key. And '1' is the value to be stored against that key.
Then use commit() to save the value in preferences.
When you need to fetch a value, you use getInt or getString etc. to fetch the value.
Example getInt("selected",0);. Here selected is the key whose value you want to fetch. 0 is the default value that will be supplied in case there is no value under the key that you have provided.
Hope this helps :)

Resources