What is the best way of doing computed properties in the Prism MVVM framework? I've got a Xamarin.Forms app with the following properties on a VM:
private string _title;
public string Title
{
get { return _title; }
set
{
SetProperty(ref _title, value);
OnPropertyChanged(() => Message);
}
}
private string _name = "John";
public string Name
{
get { return _name; }
set
{
SetProperty(ref _name, value);
OnPropertyChanged(() => Message);
}
}
public string Message
{
get { return String.Format("{0},{1}", Name, Title); }
}
The code works just fine. However, the Prism library is warning me on the OnPropertyChanged statements to use RaisePropertyChanged which will avoid the use of magic strings and that OnPropertyChanged with an expression is less efficient.
Is there some other method to notify the view to re-read "Message" whenever name or title change?
It got me to thinking maybe Prism has a way to set things up so that "Name" and "Title" don't have to be aware of Message in order for Message to be updated. This would be preferable if possible. What is the "Prism" way of doing computed properties? I cannot find any examples of it in their Xamarin.Forms documentation.
If you're trying to do this the harder way you can do something like the following:
public class FooViewModel : BindableBase
{
private string _foo;
public string Foo
{
get => _foo;
set => SetProperty(ref _foo, value, () => RaisePropertyChanged(nameof(FooBar)));
}
public string FooBar => $"{Foo} Bar";
}
If you want to make your life a little easier, install PropertyChanged.Fody and you can just have a ViewModel like the following:
public class SomeViewModel : BindableBase
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName => $"{FirstName} {LastName}";
}
Fody should give you an empty Weavers.xml, you'll just want to update it to look like:
<?xml version="1.0" encoding="utf-8"?>
<Weavers>
<PropertyChanged EventInvokerNames="RaisePropertyChanged" />
</Weavers>
Related
im trying to make an app and got a slight problem. my structure looks like this:
public class BaseModel
{
[Key]
private int _Id;
public int Id {
get { return _Id; }
set { _Id = value; }
}
}
public class SupplierModel : BaseModel
{
[ForeginKey("CountryCode")] // This should map to say "se" or "no" or whatever in the CountryModel table
public virtual CountryModel Country;
}
public class CountryModel : BaseModel
{
private string _CountryCode;
[Key] // This should be another key in the table to get the actual country.
public string CountryCode {
get { return _CountryCode; }
set { _CountryCode = value; }
}
private string _CountryName;
public string CountryName {
get { return _CountryName; }
set { _CountryName = value; }
}
}
Now i want SupplierModel to link to CountryModel (Works fine by the Id) but i want it to be the country code to be the relationship not the Id between the Entities.
So accessing CountryModel.Country should map to the CountryModel table and pull out the one that matches the country model.
Hope i didnt mess it up totaly for you, hard to explain when i do not fully understand Entity framework and database relations .. trying to learn =)
I've got a ValidationAttribute that looks like this:
public class RegistrationUniqueNameAttribute : ValidationAttribute
{
public IRepository<User> UserRepository { get; set; }
public override bool IsValid(object value)
{
//use UserRepository here....
}
}
In my container setup (in app start) I have this:
builder.Register(c => new RegistrationUniqueEmailAttribute
{
UserRepository = c.Resolve<IRepository<User>>()
});
However, when debugging, the value of UserRepository is always null, so the property isn't getting injected.
Have I set up my container wrong?
I'd really rather not have to use DependencyResolver.Current.GetService<IRepository<User>>() as this isn't as testable...
No, Autofac v3 doesn't do anything special with ValidationAttribute and friends [Autofac.Mvc does lots of powerful things e.g., with filter attributes].
I solved the problem indirectly in this answer, enabling one to write:
class MyModel
{
...
[Required, StringLength(42)]
[ValidatorService(typeof(MyDiDependentValidator), ErrorMessage = "It's simply unacceptable")]
public string MyProperty { get; set; }
....
}
public class MyDiDependentValidator : Validator<MyModel>
{
readonly IUnitOfWork _iLoveWrappingStuff;
public MyDiDependentValidator(IUnitOfWork iLoveWrappingStuff)
{
_iLoveWrappingStuff = iLoveWrappingStuff;
}
protected override bool IsValid(MyModel instance, object value)
{
var attempted = (string)value;
return _iLoveWrappingStuff.SaysCanHazCheez(instance, attempted);
}
}
(And some helper classes inc wiring to ASP.NET MVC...)
First of all, I have read this post and did not find the answer for my problem.
I am not sure if this is an aggregated Model class or an aggregated ViewModel class, but this is what I have:
In my WPF (with Prism) application, I have a view 'Filter Customers View' that connects to a service and requests a list of 'Customer' objects, based on a filter.
The list that is returned from the service is this :
List<CustomerDTO> FilteredCustomers;
And the CustomerDTO looks like this:
public class CustomerDTO
{
public Guid CustomerId;
public String Name;
public String Address;
public String PhoneNumber;
public OrderInfoDTO LastOrderInformation;
public List<OtherClass> ListOfSomething;
}
And the OrderInfoDTO looks like this:
public class OrderInfoDTO
{
public Guid OrderId;
public DateTime OrderDate;
public int NumberOfProducts;
public double TotalAmountSpent;
}
And the OtherClass looks like this:
public class OtherClass
{
public Guid Id;
public String SomeText;
}
As you can see - the customer might or might not have a 'Last Order',
I would like to wrap the 'CustomerDTO' object in a ViewModel,
so that I can bind it to the view.
This is what I thought of doing :
public class CustomerViewModel : NotificationObject
{
private CustomerDTO _customerDTO;
public CustomerViewModel(CustomerDTO customerDTO)
{
_customerDTO = customerDTO;
}
public Guid CustomerId
{
get { return _customerDTO.CustomerId; }
set { _customerDTO.CustomerId = value; RaisePropertyChanged("CustomerId "); }
}
public String Name
{
get { return _customerDTO.Name; }
set { _customerDTO.Name = value; RaisePropertyChanged("Name"); }
}
public String Address
{
get { return _customerDTO.Address; }
set { _customerDTO.Address = value; RaisePropertyChanged("Address"); }
}
public String PhoneNumber
{
get { return _customerDTO.PhoneNumber; }
set { _customerDTO.PhoneNumber= value; RaisePropertyChanged("PhoneNumber"); }
}
}
.
Questions:
First of all - is 'CustomerDTO' what is known as a Model ? And is 'OrderInfoDTO' also a Model ? and what about 'OtherClass' ?
How do I treat the 'OrderInfoDTO' in my CustomerViewModel class ? Do I create a 'ViewModel' for it also ? where do I create the 'OrderInfoDTO' view-model ??? What happens if now someone updates the customer and sets the 'OrderInfoDTO' value ?
How do I treat the list of 'OtherClass' in my CustomerViewModel class ? Do I create an ObservableCollection for it ? What happens if someone will want to delete an item in it or update an item in it or add an item to it ?
Think about it this way:
The View is your UI that you would bind elements from the View Model to using the {Binding Path=, Mode=TwoWay -- If you want to update based upon the user input
The Model is only the data, this could a record set, file, database records etc. So CustomerDTO and OrderInfoDTO are models.
The View Model is your link between the data (Model) and the UI (View). It will allow to you change the data so it's easier to present on the UI
You would need to use ObservableCollection in all instances where there's a list that could change in the background.
You don't need a view model for OrderInfoDTO unless you need a view to update that data. If you are presenting a CustomerDTO info with OrderInfoDTO in it, then making it a property of the CustomerDTO view model would be fine.
I am learning some good code practice that's why i was going through some code, some thing i could not understand in it. It has made property in a separate class for each entity like in userClass it has property
#region public properties
private int uid;
public int userId
{
get { return uid; }
set { uid = value; }
}
private string uName;
public string userName
{
get { return uName; }
set { uName = value; }
}
private string pwd;
public string password
{
get { return pwd; }
// set { pwd = value; }
}
private string uAddress;
public string userAddress
{
get { return uAddress; }
set { uAddress = value; }
}
private string fName;
public string firstName
{
get { return fName; }
set { fName = value; }
}
private string lName;
public string lastName
{
get { return lName; }
set { lName = value; }
}
private string uPhone;
public string userPhone
{
get { return uPhone; }
set { uPhone = value; }
}
private string uMobile;
public string userMobile
{
get { return uMobile; }
set { uMobile = value; }
}
private int secretQuestion;
public int securityQuestion
{
get { return secretQuestion; }
set { secretQuestion = value; }
}
private string userAnswer;
public string answer
{
get { return userAnswer; }
set { userAnswer = value; }
}
#endregion
and from the business logic class it uses the property instead of using directly any entity's attribute name, but i am confuse whats there need to make a property like this?
other then this it has got enums for database column name which has a clear reason behind this that if in near future we have to change the database table's fields name then we don't have to change through out the whole business logic class and we can make changes to enum directly, But what is there use of creating property like this please elaborate me on this
Are you really asking why it uses properties instead of having public fields?
Fields are an implementation detail - they're how data is stored, which shouldn't be something the outside world cares about, at least for 99% of types. Properties are part of the contract that a type has in terms of its API - the implementation is up to the type. In other words, it's a matter of encapsulation. Properties can be expressed in interfaces, as abstract methods etc, precisely because they keep the contract and the implementation separate.
Additionally, properties make databinding, debugging and various other things simpler. I have an article about why properties matter, which you may find useful.
Having said all of this, those properties are implemented in a tedious way - and they don't obey .NET naming conventions. I would have written them as:
public int UserId { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
// etc
Properties can be defined on Interfaces, but member fields cannot. So if you needed to refactor this class to a class that implements an interface, you can put the properties on the interface (and then have other classes that implement them as well.)
Some similar questions:
Public Fields versus Automatic Properties
Property vs public field.
In additional to above: Actually you can easily decide public field or property by yourself. It is quite easier to understand that:
(1) Name is a property of class Person
(2) Speed is a property of class Plane
(3) Empty is a public field of class String. If you say String has a property named Empty, it's really weird. And String has a property Length is easy to understand.
I'm familiar with this new syntax sugar:
public string Name { get; set; }
But what if I was the setter of that variable to have some sort of checking. For example, I want to convert the entire string that is supposed to be Set to all lowercases.
public string Name
{
get;
set
{
????
}
}
You will need a backing field for both the getter and setter (you can't have a partially automatic property):
private string name;
public string Name
{
get
{
return name;
}
set
{
// do validation or other stuff
name = value.ToLower();
}
}
You can't define a partially-automatic property. You would have to do things the old fashioned way: define backing field and implement the getter and setter logic yourself.
private string _name;
public string Name
{
get {return _name;}
set
{
_name = value.ToLower();
}
}
Then you cannot use the auto generated get/set feature:
string _name;
public string Name {
set { _name = value.ToLower(); }
set { return _name; }
}
public string Name { get; set; } These are called Auto Implemented Properties. In C# 3 and later you can use this syntax for property. But if you want to do any operation on the value before setting, then this is not helpful . One more disadvantage is ,you have to use both set and get,you can't declare only getter. Alternate is to make the setter private. In your case, you have to use the older version of properties.
private string _name;
public string Name
{
get {return _name;}
set
{
//do any operation
_name = value.ToLower();
}
}