I am new to MVVM and have written a small app to test the waters and get familiar with the pattern. The main function of my app takes too long to not have some sort of user feedback that the process is continuing along. What would be the recommended way to place the call in a separate thread and provide feedback for a progress bar? The ViewModel code for the function is below. Thanks for the help.
public DataView Data
{
get
{
return resultsView;
}
set
{
if (value == resultsView)
{
return;
}
resultsView = value;
RaisePropertyChanged("Data");
}
}
private void SetData()
{
Data = RetrieveData.GetPartData(SelectedTeam, SelectedYear).DefaultView;
}
public RelayCommand GetData
{
get;
private set;
}
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel()
{
// Initializers for other part of ViewModel
// Teams = RetrieveData.GetTeams();
// Years = RetrieveData.GetYears();
GetData = new RelayCommand(SetData);
}
I'm not completely versed on MVVM multi-threading yet, but this link seems quite do-able : WPF Multithreading: Using the BackgroundWorker and Reporting the Progress to the UI.
NOW, what I would try is something like this:
worker.DoWork += delegate(object s, DoWorkEventArgs args)
{
Data = RetrieveData.GetPartData(SelectedTeam, SelectedYear).DefaultView;
};
Related
My aim is to access bindable property across the the App. But My current framework ViewModel Instance create multiple time
My Requirement : I have the cart count in the bottomTray(CheckuoutViewModel) i want to increase the cart count any where in the app page, but in this cart count not update when back click, its only working on forward navigation, the reason behind CheckoutViewModel instance create each and every time. so that i'm try to instant creation at earlier.
Here I'm list out sample ViewModel and calling method
Login ViewModel
Checkuout ViewModel(This view model common for all page)
BaseNavigationViewModel(Its BaseViewModel)
As of now i'm calling when BindinContext each and every time like,
new LoginViewMode(navigation)
new CheckoutViewModel(navigation)
what will do to create all ViewModel instance when app start time like ViewModel Locator?
Im tried
public static ViewModelLocator Locator
{
get { return locator ?? (locator = new ViewModelLocator()); }
}
And ViewModel Locator
public ViewModelLocator()
{
navigation = App.Current.MainPage.Navigation;
}
internal CustomTabBarViewModel CustomTabBarVM
{
get
{
return customTabBarVM ?? (customTabBarVM = new CustomTabBarViewModel(navigation));
}
}
And CustomTabBar.xaml.cs
public CustomTabBar()
{
viewModel = App.Locator.CustomTabBarVM;
InitializeComponent();
BindingContext = viewModel;
}
and Expectation
App.Locator.CustomTabBarVM.BadgeCartCount = OrderObject.Instance.ORDER_OBJECT.Items.Count;
This approach is working fine but it's create some navigation issues
A singleton instance is a common feature of virtually all MVVM frameworks (Prism, FreshMVVM etc). If you aren't using a framework (if you aren't, I would STRONGLY advise you consider using one), below is a solution.
To obtain a single instance of a ViewModel you can use the App class to host the object and access it whenever you need.
Create a public static property of your ViewModel:
public static MyViewModel MyViewModelInstance { get; }
Create an instance in the constructor of the app
public App()
{
InitializeComponent();
MyViewModelInstance = new MyViewModel();
var myPage = new MyPage()
{
BindingContext = MyViewModelInstance
};
var navPage = new NavigationPage(myPage);
MainPage = navPage;
}
Whenever you create a new page, access the shared instance
// This method is just an example of how you might create a new page and wire up the view model
async void GoNextClicked(System.Object sender, System.EventArgs e)
{
var myPage = new MyPage()
{
BindingContext = App.MyViewModelInstance
};
await this.Navigation.PushAsync(myPage);
}
This approach comes with a few caveats, you are creating instances when the app loads not when they are needed (Eagerly loading). So a performance optimisation would be to use Lazy<T> to handle the creation of these objects. However this is logic that has already been written for you in MVVM frameworks, they are there to help you and you should be using them.
Lazy Load
You can save memory and performance at startup by lazy loading the viewmodel, here is this example rewritten to support this pattern:
public static MyViewModel MyViewModelInstance
{
get => _myViewModelInstanceFactory.Value;
}
private static Lazy<MyViewModel> _myViewModelInstanceFactory = new Lazy<MyViewModel>(() => new MyViewModel(), true);
public App()
{
InitializeComponent();
var myPage = new MyPage()
{
BindingContext = MyViewModelInstance
};
var navPage = new NavigationPage(myPage);
MainPage = navPage;
}
Now this object won't be created until it is accessed by your code, and once it has been accessed once it has already been created and will go on to live in memory for the rest of your apps lifecycle.
Axemasta has good answer about re-use of a shared view model instance.
I'll give an alternative approach to the underlying need given in one comment: how to have a static property (so the value is common), and Bind to it when Binding to an instance.
Use this approach if you do want a different CheckoutViewModel for each new page. For example, if there are other properties that should be set up differently, depending on the page.
public class CheckoutViewModel : : INotifyPropertyChanged // or your MVVM library's base class for ViewModels.
{
public static int SharedCount { get; set; }
public void IncrementCount()
{
Count = Count + 1;
}
public int Count {
get => SharedCount;
set {
// Exact code might be simpler if using an MVVM library.
if (SharedCount != value)
{
SharedCount = value;
OnPropertyChanged("Count");
}
}
}
}
}
LIMITATION: This assumes that only the current instance of CheckoutViewModel is visible; if you need to "notify" OTHER Views (update other CheckoutViewModel instances), then you'll need a "publish/subscribe" solution. In Xamarin Forms, one such solution is MessagingCenter.
I have a following problem. I register my components and initialize them in Unity like this (example is for a Console application):
public class SharePointBootstrapper : UnityBootstrapper
{
...
public object Initialize(Type type, object parameter) =>
Container.Resolve(type,
new DependencyOverride<IClientContext>(Container.Resolve<IClientContext>(parameter.ToString())),
new DependencyOverride<ITenantRepository>(Container.Resolve<ITenantRepository>(parameter.ToString())));
public void RegisterComponents()
{
Container
.RegisterType<IClientContext, SharePointOnlineClientContext>(SharePointClientContext.Online.ToString())
.RegisterType<IClientContext, SharePointOnPremiseClientContext>(SharePointClientContext.OnPremise.ToString())
.RegisterType<ITenantRepository, DocumentDbTenantRepository>(SharePointClientContext.Online.ToString())
.RegisterType<ITenantRepository, JsonTenantRepository>(SharePointClientContext.OnPremise.ToString());
}
}
public enum SharePointClientContext
{
Online,
OnPremise
}
class Program
{
static void Main(string[] args)
{
...
bootstrap.RegisterComponents();
var bla = bootstrap.Initialize(typeof(ISharePointManager), SharePointClientContext.Online);
}
}
So, I register my components in MVC, WCF, Console etc. once with RegisterComponents() and initialize them with Initialize().
My question is, if I want to initialize specific named registration at runtime, from e.g. user input, can it be done otherwise as the code presented (with InjectionFactory or similar)?
This code works fine, but I'm not happy with its implementation. I have a feeling that it could be written in RegisterComponents() instead of Initialize() so that it accepts a parameter of some type, but I don't know how to do it.
Or, is maybe my whole concept wrong? If so, what would you suggest? I need to resolve named registration from a parameter that is only known at runtime, regardless of the technology (MVC, WCF, Console, ...).
Thanks!
Instead of doing different registrations, I would do different resolves.
Let's say that you need to inject IClientContext, but you want different implementations depending on a runtime parameter.
I wrote a similiar answer here. Instead of injecting IClientContext, you could inject IClientContextFactory, which would be responsible for returning the correct IClientContext. It's called Strategy Pattern.
public interface IClientContextFactory
{
string Context { get; } // Add context to the interface.
}
public class SharePointOnlineClientContext : IClientContextFactory
{
public string Context
{
get
{
return SharePointClientContext.Online.ToString();
}
}
}
// Factory for resolving IClientContext.
public class ClientContextFactory : IClientContextFactory
{
public IEnumerable<IClientContext> _clientContexts;
public Factory(IClientContext[] clientContexts)
{
_clientContexts = clientContexts;
}
public IClientContext GetClientContext(string parameter)
{
IClientContext clientContext = _clientContexts.FirstOrDefault(x => x.Context == parameter);
return clientContext;
}
}
Register them all, just as you did. But instead of injecting IClientContext you inject IClientContextFactor.
There also another solution where you use a Func-factory. Look at option 3, in this answer. One may argue that this is a wrapper for the service locator-pattern, but I'll leave that discussion for another time.
public class ClientContextFactory : IClientContextFactory
{
private readonly Func<string, IClientContext> _createFunc;
public Factory(Func<string, IClientContext> createFunc)
{
_createFunc = createFunc;
}
public IClientContext CreateClientContext(string writesTo)
{
return _createFunc(writesTo);
}
}
And use named registrations:
container.RegisterType<IClientContext, SharePointOnlineClientContext>(SharePointClientContext.Online.ToString());
container.RegisterType<IClientContext, SharePointOnPremiseClientContext>(SharePointClientContext.OnPremise.ToString());
container.RegisterType<IFactory, Factory>(
new ContainerControlledLifetimeManager(), // Or any other lifetimemanager.
new InjectionConstructor(
new Func<string, IClientContext>(
context => container.Resolve<IClientContext>(context));
Usage:
public class MyService
{
public MyService(IClientContextFactory clientContextFactory)
{
_clientContextFactory = clientContextFactory;
}
public void DoStuff();
{
var myContext = SharePointClientContext.Online.ToString();
IClientContextclientContext = _clientContextFactory.CreateClientContext(myContext);
}
}
My app flow is as follows (simplified for clarity):
User GETs a page from "/page1"
User performs actions on the page (adds text, clicks, etc..), while Signalr communicates this data to the server, which performs heavy calculations in the background, and the results of those are returned to the page (lets call those "X").
When the user is finished with the page, he clicks a link to "/page2", that is returned by Nancy. This page is built using a Model that is dependent on X.
So, how do I build that Model based on X? How can signalr write to the user session in a way that Nancy can pick up on?
(I'm looking for a "clean" way)
Pending formal integration of Signalr & Nancy, this is what I came with. Basically, I share an IOC container between the two, and use an object (singleton lifetime) that maps users to state.
How to share an IOC container using the built in TinyIOC:
Extend Signalr's DefaultDependencyResolver
public class TinyIoCDependencyResolver : DefaultDependencyResolver
{
private readonly TinyIoCContainer m_Container;
public TinyIoCDependencyResolver(TinyIoCContainer container)
{
m_Container = container;
}
public override object GetService(Type serviceType)
{
return m_Container.CanResolve(serviceType) ? m_Container.Resolve(serviceType) : base.GetService(serviceType);
}
public override IEnumerable<object> GetServices(Type serviceType)
{
var objects = m_Container.CanResolve(serviceType) ? m_Container.ResolveAll(serviceType) : new object[] { };
return objects.Concat(base.GetServices(serviceType));
}
}
Replace Signalr's default DependencyResolver with our new one
public class Bootstrapper : DefaultNancyBootstrapper
{
protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
{
CookieBasedSessions.Enable(pipelines);
// Replace UserToStateMap with your class of choice
container.Register<IUserToStateMap, UserToStateMap>();
GlobalHost.DependencyResolver = new TinyIoCDependencyResolver(container);
RouteTable.Routes.MapHubs();
}
}
Add IUserToStateMap as a dependency in your hubs and Nancy modules
public class MyModule : NancyModule
{
public MyModule(IUserToStateMap userToStateMap)
{
Get["/"] = o =>
{
var userId = Session["userId"];
var state = userToStateMap[userId];
return state.Foo;
};
}
}
public class MyHub : Hub
{
private readonly IUserToStateMap m_UserToStateMap;
public MyHub(IUserToStateMap userToStateMap)
{
m_UserToStateMap = userToStateMap;
}
public string MySignalrMethod(string userId)
{
var state = userToStateMap[userId];
return state.Bar;
}
}
What I would really want, is a way to easily share state between the two based on the connection ID or something like that, but in the meantime this solution works for me.
Did you arrive hear looking for a simple example of how to integrate Nancy and SignalR? I know I did.
Try this question instead (I self-answered it).
SignalR plus NancyFX : A simple but well worked example
I'm completely new to CM and also to learn it I'm migrating an application from MVVM light to Caliburn Micro. In my original code, I had a VM which responds to some UI actions (via commands) to replace some text into a string. The position is given by the view, using the textbox selection.
So the VM has (1) a bound string property representing the textbox's text, (2) another bound string property to represent the new text to be added, and (3) needs to know selection start and length in order to replace the right portion of text with the new one.
In my original code, I had a custom DialogMessage-derived object sent in the VM command implementation with a couple of properties for selection data: when the command was issued, the message was sent, and the view received it and filled it with its textbox selection start and length; then the VM was called back and could use these data.
Which would be the best way of implementing this in CM? I'd prefer the VM to remain agnostic of the view, so I don't like too much the idea of accessing the view from it. I'd rather opt for a "message"-based mechanism like the above, but I'm not sure how I can implement it in CM: I would probably look at IResult, but most of the samples I find are related to coroutines and I'm not sure how to relate the void ReplaceText() method of the VM to the view code behind.
Could anyone point me in the right direction, and/or to some code samples about dialog-like interactions between VM 'command' methods and view? Thanks!
I'd probably look at the IResult option. You'll have access to the view so code that you would have had in the code behind can be in your Result and not in your VM.
Here is code from a ShowDialog result. I believe I grabbed it from the CM discussion group. Search the discussion group for ShowDialog for more examples. The GameLibrary sample that comes with CM also has some.
public class ShowDialog : IResult
{
private readonly Type _screenType;
private readonly string _name;
[Import]
public IWindowManager WindowManager { get; set; }
public ShowDialog(string name)
{
_name = name;
}
public ShowDialog(Type screenType)
{
_screenType = screenType;
}
public void Execute(ActionExecutionContext context)
{
var screen = !string.IsNullOrEmpty(_name)
? IoC.Get<object>(_name)
: IoC.GetInstance(_screenType, null);
Dialog = screen;
WindowManager.ShowDialog(screen);
var deactivated = screen as IDeactivate;
if (deactivated == null)
Completed(this, new ResultCompletionEventArgs());
else
{
deactivated.Deactivated += (o, e) =>
{
if (e.WasClosed)
{
Completed(this, new ResultCompletionEventArgs());
}
};
}
}
public object Dialog { get; private set; }
public event EventHandler<ResultCompletionEventArgs> Completed = delegate { };
public static ShowDialog Of<T>()
{
return new ShowDialog(typeof (T));
}
}
edit: If you extend TextBox you can bind SelectedText.
public class TextBoxEx : TextBox
{
public static readonly DependencyProperty SelectedTextProperty = DependencyProperty.Register("SelectedText", typeof(string), typeof(TextBoxEx), new PropertyMetadata("oa"));
public TextBoxEx()
{
SelectionChanged += UpdateDependencyProperty;
}
private void UpdateDependencyProperty(object sender, RoutedEventArgs e)
{
SelectedText = base.SelectedText;
}
public new string SelectedText
{
get { return GetValue(SelectedTextProperty).ToString(); }
set { SetValue(SelectedTextProperty, base.SelectedText); }
}
}
then:
<SLTest:TextBoxEx x:Name="MyTextBox2"
Grid.Row="1"
Width="200"
SelectedText="{Binding SelectedText, Mode=TwoWay}"
Text="This is some text." />
Being new to RhinoMocks and Unit Testing, I have come accross an issue that I cannot seem to find a resolution to (no matter how much documentation I read).
The issue is this: I have created an Interface that exposes 5 Events (to be used for a view in ASP.NET and the MVP Supervisory Controller pattern..... I know, I should be using MVC, but that's a whole other issue). Anyway, I want to test that when a certain event fires on the view, we'll call it "IsLoaded", that a method inside of my Presenter is called and, using Dependency Injection, a value is returned from the Dependency and set to the view. Here is where the problem starts: when I use Expect.Call(Dependency.GetInfo()).Return(SomeList), the Call never executes (without the mock.ReplayAll() method being invoked). Well, when I invoke the ReplayAll method, I get ExpectationExceptions because of the Subscription by the Presenter object to the other Events exposed by the View Interface.
So, for me to test that IView.IsLoaded has fired, I want to verify that IView.ListOfSomething has been updated to match the list I passed in via the Expect.Call(). However, when I set the expectation, the other Event subscriptions (which occur straight out of the constructor for the Presenter) fail the #0 Expectations of the test. What I get is, view.Save += this.SaveNewList tosses up a RhinoMocks ExpectationViolationException.
My million dollar question is this: Is it necessary I set expectations for ALL of my events (via [Setup]), or is there something that I'm missing/not understanding about how Unit Testing or RhinoMocks works?
Please bear in mind I am extremely new to Unit Testing, and therefore RhinoMocks. If it appears I don't know what I'm talking about, please feel free to point that out.
I'm working on a project where we used MVP and rhino mocks as well. What we did was simply expect all event subscriptions in every test.
private void SetupDefaultExpectations()
{
_mockView.Initializing += null; LastCall.IgnoreArguments();
_mockView.SavingChanges += null; LastCall.IgnoreArguments();
}
Then we built a extension method on IMockedObject (from RhinoMocks) to trigger events in the unit tests and un-wrap exceptions so that they can be expected in the standard NUnit way.
static class IMockedObjectExtension
{
public static void RaiseEvent(this IMockedObject mockView, string eventName, EventArgs args)
{
EventRaiser eventraiser = new EventRaiser(mockView, eventName);
try
{
eventraiser.Raise(mockView, args);
}
catch (TargetInvocationException ex)
{
throw ex.InnerException;
}
}
public static void RaiseEvent(this IMockedObject mockView, string eventName)
{
RaiseEvent(mockView, eventName, EventArgs.Empty);
}
}
This could then be used from the unit test like this
using(_mocks.Record())
{
Expect.Call(dependency.GetInfo()).Return(someList);
}
using(_mocks.Playback())
{
Presenter presenter = new Presenter(_mockView, dependency);
(_mockView as IMockedObject).RaiseEvent("SavingChanges");
}
To eliminate duplication between presenter tests we have refactored this to a BasePresenterTest base class which sets up this basic structure for all presenter tests and exposes helper methods to the sub class.
public abstract class BasePresenterTest<VIEW> where VIEW : IBaseView
{
protected MockRepository _mocks;
protected VIEW View { get; private set; }
protected abstract void SetUp();
protected abstract void TearDown();
protected abstract void SetupDefaultExpectations();
[SetUp]
public virtual void BaseSetUp()
{
_mocks = new MockRepository();
View = _mocks.CreateMock<VIEW>();
SetUp();
}
[TearDown]
public virtual void BaseTearDown()
{
TearDown();
View = null;
_mocks = null;
}
protected virtual void BaseSetupDefaultExpectations()
{
//Setup default expectations that are general for all views
SetupDefaultExpectations();
}
protected virtual IDisposable Record()
{
IDisposable mocksRecordState = _mocks.Record();
BaseSetupDefaultExpectations();
return mocksRecordState;
}
protected virtual IDisposable Playback()
{
return _mocks.Playback();
}
protected void RaiseEventOnView(string eventName)
{
(View as IMockedObject).RaiseEvent(eventName);
}
}
This eliminates alot of code from the tests in our project.
We still use a old version of RhinoMocks but I will try to update this once we move to a later version.