Can Mapster work with readonly collections? - c#

I wanted to use Mapster to map some classes. My origin class is this:
public partial class Componente : ObservableObject
{
public Componente() { }
public Componente(long paramLgId) : base()
{
this.Id = paramLgId;
}
[ObservableProperty]
long _id;
private readonly HashSet<PrecioHistorico> _preciosHistorico = new HashSet<PrecioHistorico>();
public IReadOnlyCollection<PrecioHistorico> PreciosHistorico => _preciosHistorico;
public void AddPrecioHistorico(PrecioHistorico paramPrecioHistorico)
{
_preciosHistorico.Add(paramPrecioHistorico);
}
public void RemovePrecioHistorico(PrecioHistorico paramPrecioHistorico)
{
_preciosHistorico.Remove(paramPrecioHistorico);
}
}
In which I have declare a readonly collection in which I can add and remove items with the methds.
But I am wondering if I the case I want to map from destination to this class it is possible, because only it is possible to add items with the methods.
Thanks.

Related

C# MVVM - shared object - NotifyOfPropertyChange

I'm doing a intro c# MVVM project (Caliburn.Micro) and I'm injecting a "job" object into each viewmodel so that the job information is accessible everywhere.
I was hoping that changes to the injected object, which might be affected by a method in one viewmodel, would be reflected in all viewmodels, and this appears to be the case, however how would the bound properties associated with that injected object be updated?
For eg. below: The instance of JobClass is passed around and is changed by the MenuBarViewModel. How would one trigger the NotifyOnPropertyChange() in the property in the MainPanelViewModel so a bound xaml control in the associated view would pick up on the changes to the underlying member.
Or is this not how is should work. Is this what the event aggregator is supposed to manage? I was hoping that passing around the job would simplify things, or is that the global variable issue... Any tips would be welcome!
Hanuman....
// MainWindowViewModel
public class MainWindowViewModel
{
private JobClass _jobClass;
private readonly IEventAggregator _eventAggregator;
public MenuBarViewModel MenuBarViewModel { get; set; }
public MainPanelViewModel MainPanelViewModel { get; set; }
public MainWindowViewModel()
{
_eventAggregator = new EventAggregator();
_jobClass= new JobClass ();
this.MenuBarViewModel = new MenuBarViewModel(_eventAggregator, _jobClass);
this.MainPanelViewModel = new MainPanelViewModel(_eventAggregator, _jobClass);
}
}
// MenuBarViewModel
public class MenuBarViewModel: PropertyChangedBase
{
IEventAggregator _events;
JobClass _jobClass;
public MenuBarViewModel(IEventAggregator eventAggregator, JobClass jobClass)
{
_events = eventAggregator;
_jobClass = JobClass;
}
public SomeMethod()
{
_jobClass.MethodToAddSomedata();
}
// MainPanelViewModel
public class MainPanelViewModel : PropertyChangedBase
{
IEventAggregator _events;
JobClass _jobClass;
public JobClass JobCase
{
get { return _jobClass; }
set
{
_jobClass= value;
NotifyOfPropertyChange(() => JobCase);
}
}
}

Winforms Databinding Notification

My model is mainly made from the 2 classes below (I actually got another class which inherits from the abstract class but it doesnt matter I think):
public abstract class FeedForEvents: BaseObservableObject
{
public abstract void ReadFeed();
public List<Event> Events { get; set; }
public void AddEvent(Event aEvent)
{
Events.Add(aEvent);
OnPropertyChanged("Events");
}
}
public class Event : BaseObservableObject
{
public string MyProp
{
get
{
return _myProp;
}
set
{
_myprop= value;
OnPropertyChanged();
}
}
}
My form contains:
private BindingList<FeedForEvents> ListFeedsForEvents = new BindingList<FeedForEvents>();
private BindingList<Event> ListEvents
=> new BindingList<Event>(ListFeedsForEvents.SelectMany(m =>m.Events).ToList());
private BindingSource pagesBindingSource = new BindingSource();
public void RefreshGrid()
{
pagesBindingSource.DataSource = ListEvents;
this.grdEvents.DataSource = pagesBindingSource;
this.grdEvents.AutoGenerateColumns = true;
}
But even if my 2 objects correctly raised the PropertyChanged notficiation, the interface never show the objects updated (unless I manually refresh them by pressing a button to manually call RefreshGrid() ). Why?

Set a Property in a ViewModel from Another ViewModel

I am trying to pass a value to a view model from another view model before navigating to the page attached to that view model.
I was previously passing it to the view, then passing it to the view model. This seems like a clumsy way of doing things.
I am not using any kind of framework so that is not an option.
At the moment the property is set as static and this works but im not sure if this is good practice.
The code:
View model 1:
This command opens the new page:
public void OpenRouteDetails()
{
RouteStopPopOverViewModel.RouteName = "TestRoute";
App.Page.Navigation.PushAsync(new RouteStopPopOverView());
}
View model 2: (RouteStopPopOverViewModel)
public static string RouteName { get; set; }
This does work but I would prefer not to use static as a way to achieve this.
Is there some way to set the RouteName property without using static or passing it through view-> view model.
I have seen some answers about this but they don't seem to answer to question clearly.
Share a controller class between view models.
The same instance has to be supplied to the constructor in both view models.
So you can set values, and listen for events in both view models.
The controller class becomes the intermediary.
public class SharedController : IControlSomething
{
private string _sharedValue;
public string SharedValue
{
get => _sharedValue;
set
{
if (_sharedValue == value)
return;
_sharedValue = value;
OnSharedValueUpdated();
}
}
public event EventHandler SharedValueUpdated;
protected virtual void OnSharedValueUpdated()
{
SharedValueUpdated?.Invoke(this, EventArgs.Empty);
}
}
public class ViewModel1
{
private readonly IControlSomething _controller;
public ViewModel1(IControlSomething controller)
{
// Save to access controller values in commands
_controller = controller;
_controller.SharedValueUpdated += (sender, args) =>
{
// Handle value update event
};
}
}
public class ViewModel2
{
private readonly IControlSomething _controller;
public ViewModel2(IControlSomething controller)
{
// Save to access controller values in commands
_controller = controller;
_controller.SharedValueUpdated += (sender, args) =>
{
// Handle value update event
};
}
}
here the sample you can achieve your requirement easily with navigation
public class ViewModelFrom : BaseViewModel
{
async Task ExecuteCommand()
{
string routeName="value to trasfer";
Navigation.PushAsync(new View(routeName));
}
}
public partial class View : ContentPage
{
public View(string routeName)
{
InitializeComponent();
BindingContext = new ViewModelTo(routeName);
}
}
public class ViewModelTo : BaseViewModel
{
public string RouteName { get; set; }
public ViewModelTo(string routeName)
{
RouteName=routeName;
}
}
If there is a hierarchy you could express that in a parent to both of them.
public class Route
{
private string Name;
}
public class RouteSelectedArgs : EventArgs
{
public Route Selected { get; set; }
}
public interface IRouteSelection
{
event EventHandler<RouteSelectedArgs> RouteSelected;
}
public interface IRouteDetails { }
public class RouteWizard
{
public UserControl view { get; set; }
private IRouteSelection _selection;
private IRouteDetails _details;
public RouteWizard(IRouteSelection selection, IRouteDetails details)
{
_selection = selection;
_details = details;
_selection.RouteSelected += Selection_RouteSelected;
view = MakeView(_selection);
}
private void Selection_RouteSelected(object sender, RouteSelectedArgs e)
{
_selection.RouteSelected -= Selection_RouteSelected;
view = MakeView(_details, e.Selected);
}
private UserControl MakeView(params object[] args)
{
////magic
throw new NotImplementedException();
}
}
As you are using the MVVM pattern, you can use one of the many MVVM Frameworks to achieve this.
I use FreshMvvm and it allow me to pass parameters between view models like this
await CoreMethods.PushPageModel<SecondPageModel>(myParameter, false);
Then in SecondPageModel I can see access the parameters in the Init method
private MyParamType _myParameter;
public override void Init(object initData)
{
base.Init(initData);
var param = initData as MyParamType;
if (param != null)
{
_myParameter = param;
}
}
You can find more details about FreshMvvm here although most MVVM frameworks have similar functionality.

Access a BindingSource in one class from another class

I have 2 classes in the same project, ProjectView and FeatureView. I need to access a BindingSource in one class from another class. I have a kluge in which I make the BindingSource scope internal instead of private. Shame, shame. Is there a better way to do this?.
// ProjectView.cs
public partial class ProjectView : System.Windows.Forms.UserControl {
}
// ProjectView.Designer.cs
partial class ProjectView {
// This should be private
internal System.Windows.Forms.BindingSource bsFeatures;
}
// FeatureView.cs
public partial class FeatureView : System.Windows.Forms.UserControl {
// Get ProjectView
Project currentProject = this._presenter.WorkItem.State["CurrentProject"] as Infrastructure.Interface.Aml.BusinessEntities.Project;
string key = System.String.Concat("Project", currentProject.Id);
this._presenter.WorkItem.State["CurrentProject"] = currentProject;
ProjectView view = _presenter.WorkItem.Items.Get<ProjectView>(key);
// Populate currentProject.Features with ProjectView.bsFeatures.List
currentProject.Features.Clear();
IList featureList = view.bsFeatures.List;
foreach (Feature feature in featureList)
{
currentProject.Features.Add(feature);
}
}
maybe something like that, not sure:
partial class ProjectView
{
// This should be private
private System.Windows.Forms.BindingSource bsFeatures;
public System.Windows.Forms.BindingSource BindingSource
{
get { return bsFeatures; }
}
public void ShareOnlyWith(FeatureView fw)
{
fw.BindingSource = bsFeatures;
}
}
of course we break one of the principles, don't depend on concretions.

How to pass value in Viewmodel to other ViewModel with mvvmcross UWP

I would like to know how to send the value of a view model to another viewmodel using mvvcross and uwp
Does anyone know how to do it?
Thanks,
You can use the IMvxNavigationService to pass and return objects. The full documentation is at: https://www.mvvmcross.com/documentation/fundamentals/navigation?scroll=26
In your ViewModel this could look like:
public class MyViewModel : MvxViewModel
{
private readonly IMvxNavigationService _navigationService;
public MyViewModel(IMvxNavigationService navigationService)
{
_navigationService = navigationService;
}
public override void Prepare()
{
//Do anything before navigating to the view
}
public async Task SomeMethod()
{
_navigationService.Navigate<NextViewModel, MyObject>(new MyObject());
}
}
public class NextViewModel : MvxViewModel<MyObject>
{
public override void Prepare(MyObject parameter)
{
//Do anything before navigating to the view
//Save the parameter to a property if you want to use it later
}
public override async Task Initialize()
{
//Do heavy work and data loading here
}
}
Using a IMvxMessenger you can send values without have a connection: https://www.mvvmcross.com/documentation/plugins/messenger?scroll=1446
public class LocationViewModel
: MvxViewModel
{
private readonly MvxSubscriptionToken _token;
public LocationViewModel(IMvxMessenger messenger)
{
_token = messenger.Subscribe<LocationMessage>(OnLocationMessage);
}
private void OnLocationMessage(LocationMessage locationMessage)
{
Lat = locationMessage.Lat;
Lng = locationMessage.Lng;
}
// remainder of ViewModel
}

Categories

Resources