How to use BindableProberty directly inside ViewModelBase class from MVVMHelper - xamarin.forms

i think my problem is about misunderstanding OOP, when my class inherits BindableObject my code is working fine , but when my Class inherits MVVMhelper ViewModelBase the SetValue and GetValue is not defined in the current context,but i need to use bindable property in my view model
public class TestViewModel : ViewModelBase
{
public TestViewModel()
{
}
public static readonly BindableProperty IsWorkingProperty =
BindableProperty.Create(nameof(IsWorking), typeof(bool),
typeof(TestViewModel), default(bool));
public bool IsWorking
{
get { return (bool)GetValue(IsWorkingProperty); }
set { SetValue(IsWorkingProperty, value); }
}
}

ViewModelBase is mvvm helper base view model which inherits from inotifypropertychanged, i say when i replase viewmodelbase with bindableobject every thing is working
you said that ViewModelBase is one class, implements INotifyPropertyChanged interface, you replace ViewModelBase with BindableObject class in your model, every thing works. Because Bindableobject is abstract class, also implements INotifyPropertyChanged interface, so you can use BindableObject implement notification function.
https://learn.microsoft.com/en-us/dotnet/api/xamarin.forms.bindableobject?view=xamarin-forms
i want to declare bindableproperty inside viewmodelbase
I don't know why you want to declare bindableproperty in ViewModelBase, if you want to do this, you must inherit BindableObject class. GetValue(BindableProperty) and SetValue are used to access the values of properties that are implemented by a BindableProperty, these methods are adstract Bindableaobject method.
Because BindableObject class has implemented INotifyPropertyChanged, so you just make ViewModelBase inherit BindableObject.

Related

Xamarin.Forms with FreshMVVM. Adding new property to FreshBasePageModel class

My project (Xamarin.Forms with FreshMVVM) contains multiple pages and I need property isBusy. My PageModels inherit from FreshBasePageModel class. I'm looking for a way to extend FreshBasePageModel class to add IsBusy property.
Is there a way to do this? Multiple inheritance is not allowed in C#.
Using extension methods i only add methods (not properties).
There is an idea to add a new class (FreshBasePageModelExt) that inherits from the FreshBasePageModel class, and use this new class as a base class for my PageModels, but perhaps there is a more elegant solution.
Mine looks like this
public class BaseViewModel : FreshBasePageModel
{
public bool IsBusy { get; set; }
public string Title { get; set; }
}
By creating this BaseViewModel and inheriting your viewModels from this will give you these attributes and then you have them in all your ViewModels.

Prism Inheriting from ViewModelBase vs BindableBase

When I create a new Xamarin.Forms application using the Prism template pack the project gets created with a MainPageViewModel that inherits from ViewModelBase
Later I create and an additional View and ViewModel say for ChatPage. This ChatPageViewModelinherits from BindableBasenot ViewModelBase as generated by the Add New dialog.
I'd like to use ViewModelBase in all my View(Models) ViewModelBase inherits from ViewModelBase : BindableBase, INavigationAware, IDestructible
I try and change the new ChatPageViewModel : BindableBase to ChatPageViewModel : ViewModelBase but the constructor gets a red squiggly error;
Error CS7036 There is no argument given that corresponds to the required formal parameter 'navigationService' of 'ViewModelBase.ViewModelBase(INavigationService)'
I see in App.xaml.cs that containerRegistry.RegisterForNavigation<NavigationPage>(); is implemented differently than the other pages containerRegistry.RegisterForNavigation<ChatPage, ChatPageViewModel>();
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<NavigationPage>();
containerRegistry.RegisterForNavigation<MainPage, MainPageViewModel>();
containerRegistry.RegisterForNavigation<SettingsPage, SettingsPageViewModel>();
containerRegistry.RegisterForNavigation<ChatPage, ChatPageViewModel>();
containerRegistry.RegisterSingleton<IXpdSettings, XpdSettings>();
containerRegistry.RegisterSingleton<IMqttDataService, MqttDataService>();
}
Is there a way I can inherit from ViewModelBase? Could / should it be implemented in the XamarinForms Prism templating?
The answer is contained in my question. See the syntax that the MainPageViewModel (that was created by the initial project creation dialog) uses - where MainPageViewModel inherits from ViewModelBase unlike subsequent pages created with Add New dialog that inherit from BindableBase. For instance ChatPageViewModel inheriting from ViewModelBase rather than BindableBase.
public class ChatPageViewModel : ViewModelBase
{
private IXpdSettings _xpdsettings;
public ChatPageViewModel(INavigationService navigationService, IXpdSettings xpdSettings)
: base(navigationService)
{
Title = "Mqtt Chat";
_xpdsettings = xpdSettings;
}
}

In 2 different ASP.Net Core API Controllers, how to ensure same endpoints are defined?

I have a requirement to have 2 data api's both of which should have same methods or endpoints to be implemented.
For example, we can have an interface to make sure, two classes will have same functions. Otherworldly, you define the contract.
public interface ITest
{
void Foo();
}
public class Test : ITest
{
public void Foo()
{
// Some logic
}
}
public class OtherTest : ITest
{
public void Foo()
{
// Some other logic
}
}
Similarly, I want controllers which will have routes and methods like below. Say in one a new action is added, the code should enforce it in the other controller.
DemoController
-- GET demo/api/action1
-- GET demo/api/action2
TestController
-- GET test/api/action1
-- GET test/api/action2
How to achieve this?
Well, you've sort of answered your own question, really. If you want to ensure that the same methods are implemented on multiple classes, that is what interfaces are for. You just make each controller implement the same interface and you're good to go.
As for ensuring a similar routing structure, you can use inheritance for that. Define a base abstract controller class. You can either choose to implement your interface here, and "implement" the required methods as abstract. Any derived class will be forced to implement any abstract methods on the base class, so it has the same effect as an interface. That technically means you can forgo the interface, if you want, and just rely on the base class forcing the implementation. Up to you. Then you can apply route attributes to your abstract methods like so:
[Route("[controller]/api")]
public abstract BaseApiController : ControllerBase
{
[HttpGet("action1")]
public abstract IActionResult Action1();
[HttpGet("action2")]
public abstract IActionResult Action2();
}
if you are dealing with different entities that requires similar business logic, you can create generic base controller and inject your common dependencies as well:
[Route("api/[controller]")]
[ApiController]
public class GenericBaseController<T> : ControllerBase where T : class
{
private readonly ILogger _logger;
public GenericBaseController(ILogger<GenericBaseController<T>> logger) {
_logger = logger;
}
[HttpGet("get")]
public IActionResult Get()
{
//...
}
[HttpPost("post")]
public IActionResult Post(T value)
{
//...
}
}
then you can extend the generic controller :
[Route("api/[controller]")]
[ApiController]
public class MyFirstController : MyFirstController<FirstModel>
{
public GenericBaseController(ILogger<MyFirstController> logger) : base(logger)
{
}
}
another one:
[Route("api/[controller]")]
[ApiController]
public class MySecondController : GenericBaseController<SecondModel>
{
public MySecondController(ILogger<MySecondController> logger) : base(logger)
{
}
}
You don't have to re-create the methods for each inherited controller if it is the same logic, or you may extend any of it if you need:
[Route("api/[controller]")]
[ApiController]
public class MyThirdController : GenericBaseController<ThirdModel>
{
public MyThirdController(ILogger<MyThirdController> logger) : base(logger)
{
}
[HttpPost("post")]
public IActionResult Post(ThirdModel value)
{
// do some logic...
return base.Post(value);
}
}

ASP.NET Accessing Interface methods, query on how method contents are called

So I have an Interface as follows
public interface IMembershipProvider
{
bool GetUserGuidFromSSOToken(string ssoToken, out string userGuid, out int statusCode);
}
And a Class as Follows which Implements the above Interface
public class MembershipProvider : IMembershipProvider
{
public bool GetUserGuidFromSSOToken(string ssoToken, out string userGuid, out int statusCode)
{
....Method Contents
}
}
And then in my Presenter I have the following
private IMembershipProvider Provider;
..
if (!Provider.GetUserGuidFromSSOToken(ObSSOCookie.Value, out userGuid, out statusCode))
And when this is called it use the code for the method from MembershipProvider class, but I am just wondering how that's possible when the MembershipProvider is never referenced in the Presenter ?
The MembershipProvider instance must be injected into the Presenter using dependency injection.
Some kind of service factory provider is usually what I do.
private IMembershipProvider Provider =
MembershipProviderService.GetDefaultProvider();
...
internal class MembershipProviderService
{
IMembershipProvider GetDefaultProvider()
{
return new MembershipProvider();
}
}

How to bind usercontrol to applications viewmodel

I am using the standard pivot template in my WP7 app.
I have the MainViewModel class defined with a few extra properties:
public class MainViewModel : INotifyPropertyChanged
{
...
private MyClass selectedKey_m;
public MyClass SelectedKey
{
get
{
...
}
set
{
if (value != this.selectedKey_m)
{
this.selectedKey_m = value;
NotifyPropertyChanged("SelectedKey");
}
}
}
}
The App class has a view model instance:
private static MainViewModel viewModel = null;
public static MainViewModel ViewModel
{
get
{
// Delay creation of the view model until necessary
if (viewModel == null)
viewModel = new MainViewModel();
return viewModel;
}
}
My MainPage.xaml.cs sets the DataContext:
DataContext = App.ViewModel;
From here, I can set up two way bindings on ListBoxes and I know it works because if I put a breakpoint on the SelecetdKey property in my viewmodel I can see the setter get called.
My problem is that I have my own user control, with a bindable property, bound to the SelectedKey property of the view model, but the property in my user control never gets set when the viewmodel gets updated and I can't figure out why.
Here is my user control:
public partial class MyUserControl : UserControl
{
public static readonly DependencyProperty SelectedKeyProperty = DependencyProperty.Register(
"SelectedKey", typeof(MyClass), typeof(MyUserControl), new PropertyMetadata(null));
public MyClass SelectedKey
{
get { return (MyClass)this.GetValue(SelectedKeyProperty); }
set { this.SetValue(SelectedKeyProperty, value); }
}
}
And here is the xaml in my main page:
<local:MyUserControl x:Name="myUC" SelectedKey="{Binding Path=SelectedKey}">
I would expect that the setter for the SelectedKey property of my user control to get called when the SelectedKey property of the view model gets changed, but it doesn't.
I've also tried setting the datacontext of my user control in the xaml:
DataContext="{Binding Path=App.ViewModel}"
The debugger does not step into the setter, don't know why.
Try adding a callback invoked on property value changes :
public static readonly DependencyProperty SelectedKeyProperty = DependencyProperty.Register(
"SelectedKey", typeof(MyClass), typeof(MyUserControl), new PropertyMetadata(MyPropertyChanged));
private static void MyPropertyChanged( object sender, DependencyPropertyChangedEventArgs args)
{
}
Solved. I had to add the static method as ptauzen suggested, but also remove the DataContext binding statement from my xaml :
DataContext="{Binding Path=App.ViewModel}"
Because the MainPage sets the datacontext in the constructor, so because my user control is a child of the main page, it inherits the data context. All I needed was to ensure the binding of my user controls properties were set up:
SelectedKey="{Binding SelectedKey}"

Resources