I have my Model class which implements INotifyPropertyChanged.
My View has 5 TextBox, 2 Button and a ListView to display grid.
In my ViewModel I was previously adding default values to the ObservableCollection of my Model class and displaying it to a ListView.
The button implementation is done using ICommand and RelayCommand.
Now I want to add data to the ObservableCollection from the user from the UI TextBox. How can I achieve that? The UI TextBox hasbindings with properties of the Model class.
My View
<ListView Name="UserGrid" Grid.Row="1" Margin="4,178,12,13" ItemsSource="{Binding UserDatas}" >
<TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,7,0,0" Name="txtUserId" VerticalAlignment="Top" Width="178" Text="{Binding UserId}" />
<TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,35,0,0" Name="txtFirstName" VerticalAlignment="Top" Width="178" Text="{Binding FirstName}" />
Like these there are 5 TextBoxes
The Model class:
public class User : INotifyPropertyChanged
{
private int userId;
private string firstName;
public int UserId
{
get
{
return userId;
}
set
{
userId = value;
RaisePropertyChanged("UserId");
}
}
}
The ViewModel:
public class UsersViewModel:INotifyPropertyChanged
{
private ObservableCollection<User> userDatas;
public ObservableCollection<User> UserDatas
{
get
{
if (userDatas == null)
{
userDatas = new ObservableCollection<User>();
}
return userDatas;
}
set
{
userDatas = value;
RaisePropertyChanged("UserDatas");
}
}
}
private CommandBase _LoadCommand;
public ICommand LoadCommand
{
get
{
if (this._LoadCommand == null)
this._LoadCommand = new CommandBase(LoadData);
return this._LoadCommand;
}
}
private void LoadData(object obj)
{
//What need to be done here to access the textboxes of UI which are binded to User.cs class.
User newUser = new User();
UserDatas.Add(newUser);
}
Now what I need to write in the LoadData method to take inputfrom textboxes from UI and store it in my ObservableCollection
There are several things you can do. Most obvious, is to have a "Add New" Command, which creates a new empty object and stores it in a CurrentUser or SelectedUser property.
This property is bound to the Template's (or Form's) context. You'd have 3 commands (Add New User, Save User, Cancel to cancel addition of a new user creation).
For example
public class UsersViewModel : INotifyPropertyChanged
{
public UsersViewModel()
{
UserDatas = new ObservableCollection<User>();
AddNewUserCommand = new RelayCommand(AddNewUser, param => !this.IsNewUser);
SaveUserCommand = new RelayCommand(SaveUser);
CancelNewUserCommand = new RelayCommand(CancelNewUser, param => this.IsNewUser);
}
private ObservableCollection<User> userDatas;
public ObservableCollection<User> UserDatas
{
get { return userDatas; }
set
{
userDatas = value;
RaisePropertyChanged("UserDatas");
}
}
private User selectedUser;
public User SelectedUser
{
get { return selectedUser; }
set
{
selectedUser = value;
RaisePropertyChanged("SelectedUser");
RaisePropertyChanged("IsNewUser");
}
}
public bool IsNewUser
{
get
{
if(SelectedUser==null)
return false;
return SelectedUser.UserId == 0;
}
}
public ICommand AddNewUserCommand { get; private set; }
public ICommand CancelNewUserCommand { get; private set; }
public ICommand SaveUserCommand { get; private set; }
private void AddNewUser()
{
SelectedUser = new User();
}
private void SaveUser()
{
// Just in case of concurency
var newUser = SelectedUser;
if(newUser == null)
{
return;
}
var isNewUser = newUser.UserId == 0;
// Persist it to the database
this.userRepository.Add(newUser);
this.userRepository.SaveChanges();
// If all worked well, add it to the observable collection
if(isNewUser)
{
// Only add if new, otherwise it should be already in the collection
UserDatas.Add(newUser)
}
}
}
But again, it's very discouraged to work directly on the model and bind it to the View. You should also create a ViewModel for your User and put validation (implement the IDataErrorInfo interface on the UserViewModel) in there and handling of state, for example tracking if the UserViewModel is dirty (i.e. data was changed).
All these are presentation concerns and not business logic, so they belong to a ViewModel and not to the Model itself.
Related
I am struggling to pass an object from one view to another using .Net Maui and a UI independent MVVM pattern.
Most or all MAUI examples I have found to date use and promote MVVM. They also tend to store the View-Models within the UI project and utilize MAUI App Shell navigation directly. This in my opinion and understanding potentially omits some of the benefits of MVVM as View Models would not work with other UI projects.
I have attempted to create a working example* with the View Models, Models and Services being in a separate UI independent project and referenced by the UI project(s) which contain the Views. Sample Project Published to GitHub I would like to update the project with a solution so it can be a working example.
I am specifically stuck where when clicking on a single object from a list of objects it opens a detail view but the object is not passed successfully. In this case my example utilizes a list of customer orders and I am attempting to open the order in a detail view when clicking on an order from the order list.
My problem lies somewhere between the XAML binding to the GoToOrdersCommand, how the command is implemented, and Order object passed to the Order View-Model.
Why do I have both a DelegateCommand and RelayCommand, I am not sure. Different examples I have viewed have used these names, I am not sure if one name is correct. Or if they should be combined into one class. I believe the only significant difference for this example is that RelayCommand accepts an object as a parameter.
Orders View-Model
namespace Orders.Common.ViewModel
{
public class OrdersViewModel : ViewModelBase
{
public ObservableCollection<Order> Orders { get; } = new();
private readonly OrderDataProvider _orderDataProvider;
private IOrderNavigation _navigationService;
public RelayCommand<Order> GoToOrdersCommand { get; }
private Order _order;
public OrdersViewModel(IOrderNavigation navigationService)
{
Orders = new ObservableCollection<Order>();
_orderDataProvider = new OrderDataProvider();
_navigationService = navigationService;
_order = new Order();
GoToOrdersCommand = new RelayCommand<Order>((order) => OrderDetails(_order));
Load();
}
public void Load()
{
var orders = _orderDataProvider.GetAllOrders();
Orders.Clear();
foreach (var order in orders)
Orders.Add(order);
}
public void OrderDetails(Order order)
{
if (order == null)
return;
_navigationService.NavigateToOrderAsync(order);
}
}
}
Order View-Model
public class OrderViewModel : ViewModelBase
{
private Order _order;
public Order Order
{
get => _order;
set
{
if (_order != value)
{
_order = value;
RaisePropertyChanged();
}
}
}
private OrderDataProvider _orderDataProvider = new OrderDataProvider();
public DelegateCommand SaveCommand { get; }
public ICommand SaveOrder { get; set; }
public OrderViewModel()
{
_order = new Order() { OrderID = -1, Customer = "", OrderDate = DateTime.Now };
SaveCommand = new DelegateCommand(Save, () => CanSave);
}
public OrderViewModel(Order order)
{
_order = order;
SaveCommand = new DelegateCommand(Save, () => CanSave);
}
public bool CanSave => !string.IsNullOrEmpty(CustomerName) && CustomerName.Length >= 3;
public void Save()
{
throw new NotImplementedException();
}
public int OrderID
{
get => _order.OrderID;
set
{
if (_order.OrderID != value)
{
_order.OrderID = value;
RaisePropertyChanged();
}
}
}
public string CustomerName
{
get => _order.Customer;
set
{
if (_order.Customer != value)
{
_order.Customer = value;
RaisePropertyChanged();
RaisePropertyChanged(nameof(CanSave));
SaveCommand.RaiseCanExecuteChanged();
}
}
}
public DateTime OrderDate
{
get => _order.OrderDate;
set
{
if (_order.OrderDate != value)
{
_order.OrderDate = value;
RaisePropertyChanged();
}
}
}
}
Inherited UI Specific Navigation
namespace TestOrders.Navigate
{
public class OrderNavigationService : IOrderNavigation
{
public void NavigateToOrdersAsync()
{
Shell.Current.GoToAsync(nameof(OrdersPage));
}
public void NavigateToOrderAsync(Order order)
{
Shell.Current.GoToAsync(nameof(OrderPage), true, new Dictionary<string, object> { { "Order", order } });
}
}
}
RelayCommand
namespace Orders.Common.ViewModel.Command
{
public class RelayCommand<T> : ICommand
{
private Action<object> _execute;
private Func<object, bool> _canExecute;
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
public event EventHandler CanExecuteChanged;
public void RaiseCanExecuteChanged()
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
}
Orders View
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TestOrders.Pages.OrdersPage"
Title="OrdersPage"
xmlns:model="clr-namespace:Orders.Common.Model;assembly=Orders.Common"
xmlns:viewmodel="clr-namespace:Orders.Common.ViewModel;assembly=Orders.Common"
x:DataType="viewmodel:OrdersViewModel">
<VerticalStackLayout>
<Label Text="Orders" HorizontalOptions="Center"/>
<CollectionView
ItemsSource="{Binding Orders}"
SelectionMode="None">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="model:Order">
<Grid Padding="10">
<Frame HeightRequest="70">
<Frame.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:OrdersViewModel}}, Path=GoToOrdersCommand}"
CommandParameter="{Binding .}"/>
</Frame.GestureRecognizers>
<Grid Padding="0" ColumnDefinitions="20,*">
<Label Text="{Binding OrderID}" Grid.Column="0"/>
<Label Text="{Binding Customer}" Grid.Column="1"/>
</Grid>
</Frame>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
</ContentPage>
*Being new to .Net Maui, XAML based UI's, MVVM patterns and inexperienced with additional topics such as interfaces and delegates there are likely best practices or coding conventions I have missed. I am also trying to avoid utilizing the MVVM community toolkit or other toolkits until I have a better understanding of MVVM and how the interfaces and commands function.
I believe that this
GoToOrdersCommand = new RelayCommand<Order>((order) => OrderDetails(_order));
should be
GoToOrdersCommand = new RelayCommand<Order>((order) => OrderDetails(order));
_order is a new instance that you create on the preceding line, NOT the instance being passed in from the view's binding
Change to OrdersViewModel Constructor
public OrdersViewModel(IOrderNavigation navigationService)
{
Orders = new ObservableCollection<Order>();
_orderDataProvider = new OrderDataProvider();
_navigationService = navigationService;
GoToOrdersCommand = new RelayCommand<Order>((order) => OrderDetails((Order)order));
GoToNewOrderCommand = new DelegateCommand(NewOrder); // Additional navigate without object
Load();
}
Additional Command method to navigate to a New/Empty Order Detail for reference added to the OrdersViewModel
private void NewOrder()
{
_navigationService.NavigateToOrderAsync();
}
Updated Order Navigation
public class OrderNavigationService : IOrderNavigation
{
public void NavigateToOrdersAsync()
{
Shell.Current.GoToAsync(nameof(OrdersPage));
}
public void NavigateToOrderAsync(Order order)
{
Shell.Current.GoToAsync(nameof(OrderPage), true, new Dictionary<string, object> { { "Order", order } });
}
public void NavigateToOrderAsync()
{
Shell.Current.GoToAsync(nameof(OrderPage));
}
}
OrderPage View Code Behind File
Added QueryProperty, a field and method to create an OrderViewModel if an Order object is provided.
[QueryProperty(nameof(order), "Order")]
public partial class OrderPage : ContentPage
{
public Order order
{
set
{
Load(value);
}
}
public OrderPage()
{
InitializeComponent();
BindingContext = new OrderViewModel();
}
private void Load(Order order)
{
if (order != null)
BindingContext = new OrderViewModel(order);
}
}
Regarding data binding and updating on ViewModel.
I've created a User class which has Id, Email, Password.
On my XAML, I've used binding to a ViewModel which has a 'User' variable.
I've also created 2 individual properties on the ViewModel for Email and Password, and binded those directly into the Entry field.
In View Model. OnProperty change of Email/Password, I want to update User Property, but the OnPropertyChange doesn't get triggered in the ViewModel, but only on the User Class itself.
Is there a way to trigger the OnPropertyChange directly on the ViewModel? I've tried OnPropertyChange(User).
The only way I've figured how to do this is by creating a new instance of User with the newly set Email & Password parameter.
Is there a better way to this than creating a new User?
It doesn't work with Binding the User.Email in XAML either.
The thing is that User class gets triggered directly and triggers its' set, and seems to bypass the LoginVM User set property.
Login Button would remain disabled if not for the RefreshUser() function.
Solution: (I've re-edited my code to show the modification)
Ok I've done it. Managed to figure out the issue with the lack of updating. It was due to the Command being an ICommand and it lacked the ChangeCanExecute function. So I created an abstract class that generates the Command and includes a function to add the Command to the button.
Also thanks to #Jason for pointing me in the right direction of adding the property listener on the VM.
It may not be ideal, but it looks like the best solution I've found scouting the net. The closest I got was a RelayCommand. So I created my own replacement for the ICommand interface.
Suggestions are welcomed. Otherwise, hope this helps some out there.
BaseViewModel
public class BaseViewModel : ObservableObject
LoginVM
public class LoginVM : BaseViewModel {
public LoginCommand loginCommand { get; set; }
private Users user;
public Users User
{
get => user;
set => SetProperty(ref user, value);
}
private string email;
public string Email
{
get => email;
set => SetProperty(ref email, value, onChanged: ()=> { RefreshUser(); });
}
private string password;
public string Password
{
get => password;
set => SetProperty(ref password, value, onChanged: () => { RefreshUser(); });
}
private void RefreshUser()
{
User = new Users() { Email = this.Email, Password = this.Password };
}
public LoginVM()
{
User = new Users();
loginCommand = new LoginCommand(this);
regNav = new RegistrationPageNavigationCommand(this);
//This was the main trigger
User.PropertyChanged += (s, e) => {
loginCommand.ChangeCanExecute();
};
}
void ApplyCommand(Button button)
{
loginCommand.ApplyActionToButton(button);
}
...
}
XAML Code:
<Entry x:Name="emailEntry" Placeholder="Email Address"
Text="{Binding Email, Mode=TwoWay}"
Keyboard="Email">
</Entry>
<Entry x:Name="passwordEntry" Placeholder="Password"
Text="{Binding Password, Mode=TwoWay}"
IsPassword="True">
</Entry>
<Button x:Name="loginButton"
Margin="0, 50, 0, 0"
Text="Log In"
Command="{Binding loginCommand}"
CommandParameter="{Binding User}"
Style="{StaticResource normalButton}"
/>
LoginCommand
public class LoginCommand : RedoneCommand
{
public LoginVM LoginVM { get; set; }
public LoginCommand(INotifyPropertyChanged viewModel) : base(viewModel)
{
LoginVM = (LoginVM)viewModel;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
var user = (Users)parameter; //Passing through specifically this type.
if (user == null) return false; //First launch - it checks and is null.
string email = user.Email, password = user.Password;
if (StringThings.IsValidEntry(email) && StringThings.IsValidEntry(password))
{
return true;
}
return false;
}
public void Execute(object parameter)
{
LoginVM.Login();
}
}
Users
[Table("Users")]
public class Users : BaseViewModel
{
private string id;
public string Id
{
get => id;
set => SetProperty(ref id, value);
}
private string email;
public string Email
{
get => email;
set => SetProperty(ref email, value, onChanged: () => { });
}
private string password;
public string Password
{
get => password;
set => SetProperty(ref password, value, onChanged: () => { });
}
RedoneCommand: (My ICommand Replacement)
namespace MVVM
{
public abstract class RedoneCommand : ICommand
{
public INotifyPropertyChanged viewModel { get; set; }
private Command command { get; set; }
public RedoneCommand(INotifyPropertyChanged viewModel)
{
this.viewModel = viewModel;
command = new Command(Execute, CanExecute);
viewModel.PropertyChanged += (s, e) => { ChangeCanExecute(); };
}
public void ApplyActionToButton(Button button)
{
button.Command = command;
}
public void ChangeCanExecute()
{
command.ChangeCanExecute();
}
abstract public event EventHandler CanExecuteChanged;
abstract public bool CanExecute(object parameter);
abstract public void Execute(object parameter);
}
}
And on LoginVM:
viewModel = new LoginVM();
viewModel.ApplyCommand(loginButton);
BindingContext = viewModel;
I have updated my comment question with the solution at the bottom.
Needs a User.PropertyChanged and a Command.ChangeCanExecute() to update the UI.
MyProduct is the model that has HasError boolean property (with OnPropertyChanged ...) that can change.
MyProductDialogViewModel is:
class ProductDialogViewModel : Notifier
{
public ProductDialogViewModel() { }
public MyProduct Product { get; set; }
public bool HasError
{
get { return Product.HasError; }
}
}
I have assigned MyProductDialogViewModel instance to BaseContentControl.DataContext to inflate a ContentControl.
This View can be inflated with different ViewModels all having HasError property using template binding.
<ContentControl x:Name="BaseContentControl" Content="{Binding}" ... >
Then I try to extract informations directly from its DataContext.
This don't work:
<Label Content="{Binding ElementName=BaseContentControl, Path=DataContext.HasError}"/>
But this works perfectly.
<Label Content="{Binding ElementName=BaseContentControl, Path=DataContext.Product.HasError}"/>
I tought it ca be a notifiy problem in the ViewModel so I have changed to this:
class ProductDialogViewModel : Notifier
{
public ProductDialogViewModel() { }
public MyProduct Product { get; set; }
public bool HasError
{
get { return Product.HasError; }
set
{
if (Product.HasError != value)
{
Product.HasError = value;
OnPropertyChanged("HasError");
}
}
}
}
but to no avail (in fact the set method is never called so it never notifies).
I don't want to directly refer to the specific Model instance cause the View can be inflated with different ViewModels.
How can I do ?
Thanks
You have to propagate the PropertyChanged event of MyProduct, i.e. subscribe to it and invoke OnPropertyChanged(nameof(HasError)) if HasError property of MyProduct being changed:
public class ProductDialogViewModel : Notifier
{
public ProductDialogViewModel() { }
private MyProduct _product = null;
public MyProduct Product
{
get { return _product; }
set
{
if (_product!=null)
{
_product.PropertyChanged -= Product_PropertyChanged;
}
_product = value;
if (_product != null)
{
_product.PropertyChanged += Product_PropertyChanged;
}
}
}
private void Product_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName==nameof(MyProduct.HasError))
{
OnPropertyChanged(nameof(HasError));
}
}
public bool HasError => Product.HasError;
}
I am new in WPF I have implemented INotifyPropertyChanged interface. I have one viewmodel containing the property "TeamMemberList". The control executes the setter part, changes the property value but the PropertyChanged event remains null.
Here is code:
ViewModelBase:
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
ViewModel:(Which inherits the viewmodelbase)
Property is
public List<Employee> TeamMemberList
{
get
{
return _teamMemberList;
}
set
{
_teamMemberList = value;
NotifyPropertyChanged("TeamMemberList");
}
}
Binding
<ListBox Margin="10" ItemsSource="{Binding TeamMemberList, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" >
when new employee added to the DB, model reads it & creates List for all emplyee then the TeamMeberList property gets updated. This is updation method for TeamMemberList
var qryEmp = from employee in ClientModel.EmployeeList
where employee.ReportingManager == UserProfile.EmployeeId
select new Employee
{
EmployeeId = employee.EmployeeId,
EmployeeName = employee.EmployeeName,
Designation = employee.Designation,
ProfilePic = employee.ProfilePic,
};
TeamMemberList = qryEmp.ToList();
And implementation of Employee
public class Employee : ViewModelBase
{
private string _employeeName;
private string _employeeId;
private string _profilePic;
private string _designation;
private string _reportinManager;
public string EmployeeName
{
get
{
return _employeeName;
}
set
{
_employeeName = value;
NotifyPropertyChanged("EmployeeName");
}
}
public string EmployeeId
{
get
{
return _employeeId;
}
set
{
_employeeId = value;
NotifyPropertyChanged("EmployeeId");
}
}
public string ProfilePic
{
get
{
return _profilePic;
}
set
{
_profilePic = value;
NotifyPropertyChanged("ProfilePic");
}
}
public string Designation
{
get
{
return _designation;
}
set
{
_designation = value;
NotifyPropertyChanged("Designation");
}
}
public string ReportingManager
{
get
{
return _reportinManager;
}
set
{
_reportinManager = value;
NotifyPropertyChanged("ReportingManager");
}
}
}
It's hard to say what the problem is when we don't see more code (eg: how you are setting the DataContext etc...).
But there is an easy way to debug your bindings by adding the following attribute to it:
<ListBox Margin="10" ItemsSource="{Binding TeamMemberList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
PresentationTraceSources.TraceLevel=High>
Adding this attribute will output the whole binding sequence to the Output window of Visual Studio. That should point out what is going wrong.
If you want to enable this for all bindings, you can also use the Visual Studio options:
Use ObserveableCollection instead of a list
My project ViewModel elements are not being found. I'm trying to implement a ViewModel within my WPF Usercontrol. However, the binding isn't working properly and there appears to be no data. I'm trying to create a ViewModel to interact with, putting generic string arrays into, and various other bits of data.
MainWindow.xaml - (Usercontrol declaration)
<panels:FilterLister Grid.Column="0" x:Name="filter1FilterLister" />
MainWindows.cs - (Within the constructor, call to usercontrol
filter1FilterLister.Initialise(typeof(Genre));
FilterListViewModel.cs
public class FilterListViewModel
{
MyEntities context = new MyEntities();
ObservableCollection<string> entries = new ObservableCollection<string>();
public Type SelectedType;
private string p_TypeName;
public string TypeName
{
get { return p_TypeName; }
set {
//p_TypeName = value;
p_TypeName = SelectedType.Name.ToString();
}
}
public FilterListViewModel() { }
public FilterListViewModel(Type selectedType)
{
if (selectedType == typeof(Artist))
{
returnedArray = Artist.ReturnArtistNames(context);
}
// put together ObservableCollection
foreach (var str in returnedArray)
{
entries.Add(str);
}
SelectedType = selectedType;
}
}
FilterLister.xaml
<Label Name="labelToBind" Content="{Binding TypeName}" Grid.Row="0" />
FilterLister.cs
public partial class FilterLister : UserControl
{
FilterListViewModel filterListViewModel;
private MyEntities context;
public FilterLister()
{
InitializeComponent();
context = new MyEntities();
}
public void Initialise(Type objectType)
{
filterListViewModel = new FilterListViewModel(objectType);
this.DataContext = filterListViewModel;
}
}
Based on your code, TypeName is null so you saw nothing on the Label. From your code, I think you want to describe like:
public string TypeName
{
get{ return SelectedType.Name.ToString();}
}
As deryck suggested, you should add INotifyPropertyChanged interface for notification, but it should not affect binding at first time. If you believe ViewModel's data is correct but not populated on UI, you should check DataContext and Binding.
You've missed implement the INotifyPropertyChanged interface in your ViewModel, it's needed to the binded property can send "refresh message" to a UI.
Here is the interface, and how you can implement this:
http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx
public class FilterListViewModel : INotifyPropertyChanged
{
MyEntities context = new MyEntities();
ObservableCollection<string> entries = new ObservableCollection<string>();
public Type SelectedType;
private string p_TypeName;
public string TypeName
{
get { return p_TypeName; }
set {
//p_TypeName = value;
p_TypeName = SelectedType.Name.ToString();
NotifyPropertyChanged();
}
}
public FilterListViewModel() { }
public FilterListViewModel(Type selectedType)
{
if (selectedType == typeof(Artist))
{
returnedArray = Artist.ReturnArtistNames(context);
}
// put together ObservableCollection
foreach (var str in returnedArray)
{
entries.Add(str);
}
SelectedType = selectedType;
}
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}