If I want to access the clipboard with MVVM how can I do it?
While you certainly can do things like Clipboard.SetText and Clipboard.GetText in your VM, if you are an MVVM purist (like me), then I would recommend creating a ClipboardService (with an appropriate interface, so you can mock it in unit tests). Something like the following:
using System.Windows;
public class ClipboardService : IClipboardService
{
public void SetText(string value)
{
Clipboard.SetText(value);
}
public string GetText()
{
return Clipboard.GetText();
}
}
Then you can reference it as a property in your VM like so:
public IClipboardService ClipboardService { get; set; }
And either set it directly as a property or include it in your constructor:
public FooViewModel(IClipboardService service) {
ClipboardService = service;
}
And when you need it, instead of calling Clipboard.SetText directly, you can use ClipboardService.SetText instead. And you can (as mentioned before) mock it in unit tests. So, if you use Moq (like I do), you could have something like:
Mock<IClipboardService> clipMock = new Mock<IClipboardService>();
clipMock.Setup(mock => mock.GetText(It.IsAny<string>())).Returns("Foo");
And instantiate your VM like so:
var fooVm = new FooViewModel(clipMock.Object);
And so on.
I realize this is an ancient post, but I was looking for some best practices on Clipboards and MVVM, made my own decision while reading this post and decided to share. Hope somebody finds it useful. :-)
SL 4 now supports text clipboard operations. This is transparent in OOB mode and requires user confirmation if not in OOB mode.
You can use Clipboard.GetText() in your view models and commands to retrieve the text content available in the clipboard.
Related
Unfortunately I have a Specflow test passing locally, but it fails on the VSO Build vNext server, and I really need to see verbose information during the test run so I can figure out what is going on.
But I'm struggling to try to inject ITestOutputHelper into a Specflow binding like so
public SomeSteps(ITestOutputHelper outputHelper)
but Specflow complains with the message
BoDi.ObjectContainerException Interface cannot be resolved: Xunit.Abstractions.ITestOutputHelper (resolution path: ...)
How on earth can view log and view output during a Specflow test?
not sure if I'm using a newer version and it's easier now, but this seems to work for me:
ScenarioContext.Current.ScenarioContainer.Resolve<ITestOutputHelper>().WriteLine("Hello");
This is the best I could come up with, it's not ideal but it does accomplish what you want.
You create a new class that implements your generated xunit class. In my example, the generated class is called YourNormalFeatureClass
public class SpecialTest : YourNormalFeatureClass
{
private Xunit.Abstractions.ITestOutputHelper helper;
public SpecialTest(ITestOutputHelper helper) : base()
{
this.helper = helper;
}
public override void ScenarioSetup(ScenarioInfo scenarioInfo)
{
base.ScenarioSetup(scenarioInfo);
// you'd want a better way to keep track of this string
TechTalk.SpecFlow.TestRunnerManager.GetTestRunner().ScenarioContext.Set(this.helper, "helper");
}
}
Now, you're able to access your XUnit ITestOutputHelper from within your steps file via
var helper = this._scenarioContext.Get<Xunit.Abstractions.ITestOutputHelper>("helper");
helper.WriteLine("output from within the steps file that will be written to xunit!");
You'd need to be defensive with that helper variable to make sure that you don't get any NullReferenceException's
The downside to this is that you now have 2 copies of the same test because you inherited the old test. So in this case you have the tests from SpecialTest and YourNormalFeatureClass. This means that you'd need to not run YourNormalFeatureClass tests and only run the SpecialTest tests.
All of this would be easily solved if SpecFlow allowed you to customize the code generation process. That way you could expose the ITestOutputHelper via the generated code. The consumption of it from within the steps would be the same.
This may be a new addition to SpecFlow since this question was asked (6 years ago), but TechTalk.SpecFlow.Infrastructure.ISpecFlowOutputHelper should solve your problem. Inject it and use it in much the same way you would with xUnit's ITestOutputHelper, e.g.
[Binding]
public class SomeSteps
{
private readonly ISpecFlowOutputHelper output;
public SomeSteps(ISpecFlowOutputHelper output)
{
this.output = output;
}
[When(#"I write some debug info")]
public void WhenIWriteSomeDebugInfo()
{
this.output.WriteLine("Hello world!");
}
}
The suggested way of using ServiceStack.NET with Silverlight is to use the Linked-Project addon. This enables two synchronous Projects and their sources, one for Silverlight, one for .NET 3.5+.
But when it comes to validation, this gets a bit annoying.
ServiceStack is using FluentValidation, which is cool. But it has changed the namespace.
So I end up with:
using MyNamespace.Model;
// HERE ----------------------------
#if SILVERLIGHT
using FluentValidation;
#else
using ServiceStack.FluentValidation;
#endif
//TO HERE------------------------
namespace HR.RoBP.Contracts.Validators.Model
{
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(r => r.Name).NotEmpty().NotNull();
}
}
}
This is not much, but it gets really annoing when writing a new validator each time. I often forget it, compile, have errors, fix it.
I know there is something changed in FluentValidation on ServiceStack.NET.
But must it be in a seperate Namespace?
I think its in the interest of servicestack to keep code files clean.
But using the the same validation on client and server forces me to do this.
If there is a elegant way to fix this issue, I would love to hear about it.
You unfortunately can't set a project-wide namespace alias. You could however try to write a template for your validator class that has that boilerplate code built in, and you can easily click Add -> New Item -> Your Validator Template.
Disclaimer: I have no prior experience in MVVM/MVC/MVP/MVWhatever, this is my very first try using any UI separation pattern.
On startup, my app needs to load data from a config file, which is needed for the application to work.
At the moment, I'm reading the config file on startup in App.xaml.cs, and I'm passing the content of the file to the view model:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
string configFile = "settings.txt";
string[] config = File.ReadAllLines(configFile);
var window = new MainWindow();
var viewmodel = new MainWindowViewModel(config);
window.DataContext = viewmodel;
window.Show();
}
}
1. Is this the "correct" MVVM way?
I'm sure that this way is better than reading the file directly in the view model (that's how I did it first), but I'm not sure if App.xaml.cs is the right place at all for reading config files.
2. Where/how do I handle errors?
The data from the config file is essential for the application.
So if the file is missing or empty, or if the data in the file is invalid, then I need to display an error message and quit the application.
My first attempt would be to put that in App.xaml.cs as well:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
string configFile = "settings.txt";
if (!File.Exists(configFile))
{
MessageBox.Show("config file missing");
Application.Current.Shutdown();
return;
}
string[] config = File.ReadAllLines(configFile);
if (config.Count() == 0)
{
MessageBox.Show("config file empty");
Application.Current.Shutdown();
return;
}
var window = new MainWindow();
var viewmodel = new MainWindowViewModel(config);
window.DataContext = viewmodel;
window.Show();
}
}
But that doesn't look "right" to me. I already didn't feel comfortable with loading the file there (see first example), so this is even worse.
Note: I know that I probably shouldn't directly call Messagebox.Show here.
Please note that this is not what I'm asking here - I know that I should replace it by something more MVVM-like, but the point is: I would still have to call that (and then close the app) from somewhere.
What I actually want to know is if App.xaml.cs is the right place for this!
3. Plus, I have another kind of error to handle:
The actual parsing of the config file is done by the model (the model is part of an existing library and the WPF app I'm building here is just a nice UI for that).
So the view model creates an instance of the model and calls the parsing method...which throws an exception if the data from the config file is invalid.
How do I handle this the "MVVM way"?
Just catching the exception in the view model and closing the whole application from there feels wrong to me.
EDIT:
To answer Will's comment about why I'm not using app.config:
I'm using a "special" configuration file because I need to load several named "sets" of value pairs from there. Here's an example file.
Basically, it's a Dictionary<string, List<ClassWithTwoStringProperties>>.
AFAIK, app.config doesn't support data like this, so the only thing I could do is save the whole thing as a blob in one property in app.config, and still do the parsing myself.
--> so I'd still have to call the parsing from somewhere in the WPF app.
I wanted a simple, human editable format
the WPF app is just a nice UI for a library, and I need a config file in the library as well
I think, this way is incorrect.
You should think about app.config as about any persisted data (e.g. database, file). If you want to access persisted data in MVVM way, you should write a service (something like IApplicationDataService) and call this service implementation from your MainWindowViewModel code. It will be more MVVMish, if you will locate this service from some ServiceLocator or inject it via IoC container - this helps to write unit tests later.
Implementation of service should return to view model initialized model instance. Something like this:
public ApplicationDataService : IApplicationDataService
{
public ApplicationModel LoadApplicationData()
{
// process app.config here
}
}
public ViewModelBase<TModel>
{
public TModel Model
{
get { return model.Value; }
}
private readonly Lazy<TModel> model = new Lazy(GetModel);
protected abstract TModel GetModel();
}
public MainWindowViewModel<ApplicationModel> : ViewModelBase
{
protected override ApplicationModel GetModel()
{
try
{
var dataService = ServiceLocator.GetService<IApplicationDataService>();
return dataService.LoadApplicationData();
}
catch (AnyException e)
{
// oops!
}
}
}
I am trying to open a *.epub file throught my application and I don't quite understand how to make it with the UIDocumentInteractionController class. I have seen the official IOS documentation and examples and some of the examples over the net but I don't understand how that class works. This is how I do it, what I achieve and what I dont understand:
I have a UIView with a UIButton:
using MonoTouch.UIKit;
using MonoTouch.Foundation;
using System.Drawing;
public class MyView : UIViewController
{
UIButton myBtn;
public MyView() :base()
{
View.Frame = new RectangleF(0,0,1024,768);
var myRect = new RectangleF(300,300,100,50);
myBtn = UIButton.FromType(UIButtonType.RoundedRect);
myBtn.Frame = myRect;
myBtn.TouchUpInside += delegate
{
var dic = UIDocumentInteractionController.FromUrl(new NSUrl("http://192.168.50.50:2020/myfile.epub"));
var dicDel = new UIDocumentInteractionControllerDelegate();
dic.Delegate = dicDel;
InvokeOnMainThread(delegate
{
var result = dic.PresentOpenInMenu(myRect, View, true);
//If I do this -> NullReferenceException because delegate is null (something about autorelease?? Don't know)
if(!result) dic.Delegate.DidDismissOpenInMenu(dic);
});
}
}
}
The weirdest thing is if I debug and inspect "dic" (without the delegate) before calling the PresentOpenInMenu() method it shows the menu (returning true) but just after doing it the app blows up on Main.cs because the autorelease thing I dont understand.
I am a little lost. Can someone help me understand this class and how can I make it work correctly? Thanks in advance.
EDIT: By the way, I used a *.txt file too with same results.
It looks like a MonoTouch bug. Setting the UIDocumentInteractionController.Delegate (or WeakDelegate property and then querying its value returns null (which will fail later on).
I'll look into this bug and update this answer if I can provide a workaround (until the bug is properly fixed in a future release of MonoTouch).
UPDATE: UIDocumentInteractionController already creates it's own internal UIDocumentInteractionControllerDelegate so you do not need to create one. The Delegate methods, like DidDismissOpenInMenu are available as events on UIDocumentInteractionController itself.
Remove your own Delegate (creation and set) and use the events and you should be fine.
UPDATE #2: The Delegate property returns null since the default UIDocumentInteractionControllerDelegate is not usable as is. It is meant to be inherited from and customized to do what you want to (and the unusable default one is not registred properly to be used). E.g.
class MyDocumentInteractionControllerDelegate : UIDocumentInteractionControllerDelegate { }
and
var dicDel = new MyDocumentInteractionControllerDelegate ();
would work, as in no NullReferenceException, but of course DidDismissOpenInMenu won't be doing anything interesting.
What are the best practices to create a site, with ability to develop plugins for it?
Like you want to create a blog module, and you want users or co-developers to add plugins to extend this module functionality.
Update:
Thanks for the ultra speed answers, but I think this is over kill for me. Isn't there a simpler solution, like I have seen blogengine plugin creation system is you just have to decorate the class plugin with [Extension].
I am kind of mid core developer, so I was thinking of base class, inheritance, interfaces, what do you think ?
Edit
I completely rewrote my answer based on your question edit.
Let me show you just how easy it is to implement a plugin architecture with just the minimal steps.
Step 1: Define an interface that your plugins will implement.
namespace PluginInterface
{
public interface IPlugin
{
string Name { get; }
string Run(string input);
}
}
Step 2: Create a plugin that implements IPlugin.
namespace PluginX
{
using PluginInterface;
public class Plugin : IPlugin
{
public string Name
{
get { return "Plugin X"; }
}
public string Run(string input)
{
return input;
}
}
}
Step 3: Run the plugin.
namespace PluginTest
{
using System;
using System.IO;
using System.Runtime.Remoting;
using PluginInterface;
class Program
{
static void Main( string[] args )
{
string pluginFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PluginX.dll");
ObjectHandle handle = Activator.CreateInstanceFrom(pluginFile, "PluginX.Plugin");
IPlugin plugin = handle.Unwrap() as IPlugin;
string pluginName = plugin.Name;
string pluginResult = plugin.Run("test string");
}
}
}
Keep in mind, this is just the basic, most straightforward example of a plugin architechure. You can also do things such as
create a plugin host to run your plugin inside of it's own AppDomain
choose either interfaces, abstract classes, or attributes to decorate your plugins with
use reflection, interfaces, IL-emitted thunks or delegates to get the late binding job done
if your design so dictates.
It's valuable to separate technical and architecturas perspectives:
In code level MEF (Managed Extensibility Framework) is a good start. Here is a simple example.
Any other DI (Dependency Injection framework) can work well to (ie. Unity)
And it's good to see this problem in architectural level:
Web Client Software Factory from p&p. Here are not only technical but arcihtectural informations about "How to create composite web applications?". See examples.. There is Modularity Boundle package.
Spring Framework.
I think it's a fast and efficient if you read&try some of those frameworks. And ofcoz read the source if you find something interessing.
Edit
if you are searching for an extensible blog engine then try Blog Engine first. It's from ASP.NET community.
This sounds like a job for the Managed Extensibility Framework from Microsoft. It's in a preview release at the moment but it would seem to be a better bet than rolling your own framework for this. There are links to guides about how to use this on the site there.
If you would like to see a real, open source application that impliments this archecture take a look at DotNetNuke.