So I looked at this link before:
http://blogs.msdn.com/b/delay/archive/2009/10/26/creating-something-from-nothing-developer-friendly-virtual-file-implementation-for-net.aspx
The class works flawlessly for Files, but it doesn't support directory's etc, does anyone have any idea how I can change the class to support it, I"m no pinvoke whiz. I've tried a million different things, overriding some code to do File Copy and Directory creation of my drop source into the TEMP directory and attempting to trigger a FileDrop, but this locks up the app entirely.
This leads me to believe that there must be a better way to enable directory structure creation as well.
The main part of the Drag and Drop operation is the DragDrop.DoDragDrop method. From the DragDrop.DoDragDrop Method page on MSDN:
public static DragDropEffects DoDragDrop(
DependencyObject dragSource,
Object data,
DragDropEffects allowedEffects
)
Of particular interest is the data parameter:
A data object that contains the data being dragged.
Notice how this parameter is of type Object, so it's completely up to you as to what object you use in the operation. Now I'm not sure what code you found from the page that you linked to, but if I were trying to drag and drop files and folders, I wouldn't need special classes to do it for me.
The simplest way to do that is to just pass the file and/or folder paths instead of the actual data. The control that the data is dropped on can access the data using the file paths just as easily as the drag source. You should be able to locate the DragDrop.DoDragDrop method from your code and easily adapt that code.
If you want to do Drag and Drop operations in the correct way, then I'd recommend that you take a look at the Drag and Drop Overview page on MSDN. It fully explains what to do and provides several code examples.
To implement drag and drop in MVVM without much experience in WPF, you can refer to 5 steps; I will outline these...
Step 1: Attached Behaviours
Add a new class to your project called Behaviours. It should look like this...
public static class Behaviours
{
#region DandBehaviour
public static readonly DependencyProperty DandBehaviourProperty =
DependencyProperty.RegisterAttached("DandBehaviour", typeof(ICommand), typeof(Behaviours),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.None,
OnDandBehaviourChanged));
public static ICommand GetDandBehaviour(DependencyObject d)
{
return (ICommand)d.GetValue(DandBehaviourProperty);
}
public static void SetDandBehaviour(DependencyObject d, ICommand value)
{
d.SetValue(DandBehaviourProperty, value);
}
private static void OnDandBehaviourChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Grid g = d as Grid;
if (g != null)
{
g.Drop += (s, a) =>
{
ICommand iCommand = GetDandBehaviour(d);
if (iCommand != null)
{
if (iCommand.CanExecute(a.Data))
{
iCommand.Execute(a.Data);
}
}
};
}
else
{
throw new ApplicationException("Non grid");
}
}
#endregion
}
This class implements an attached dependency property which can be reached from both your Xaml and your View Model. It hooks the "Drop" event and invokes a command on it.
Step 2: Instrument the Xaml
In this step you need to add the name space to the Xaml so that it can find the behaviours class in Step 1. It looks something like this...
xmlns:b="clr-namespace:DdMvvm"
This statement assigns the alias 'b' to the behaviours. Then you tell the WPF root window to accept drops...
AllowDrop="true"
Then you can add the behaviour to your logical tree thusly...
<Grid AllowDrop="True" b:Behaviours.DandBehaviour="{Binding DandCommand}">
<DockPanel Background="Bisque" AllowDrop="True"/>
</Grid>
Step 3: Add command support
Download Josh Smith's 'Relay Command' from http://msdn.microsoft.com/en-us/magazine/dd419663.aspx For completeness purposes, it is given here as...
public class RelayCommand : ICommand
{ //http://msdn.microsoft.com/en-us/magazine/dd419663.aspx
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
private readonly Action<object> _execute;
private readonly Predicate<object> _canExecute;
}
Step 4: Write the View Model
A View Model looks like this...
public class ViewModel : INotifyPropertyChanged
{
public ICommand DandCommand { get; set; }
public ViewModel()
{
DandCommand = new RelayCommand(ExecuteDandCommand, CanExecuteDandCommand);
}
private void ExecuteDandCommand(object obj)
{
if (obj != null)
{
IDataObject ido = obj as IDataObject;
if (ido != null)
{
var fileDrop = ido.GetData(DataFormats.FileDrop, true);
var filesOrDirectories = fileDrop as String[];
if (filesOrDirectories != null && filesOrDirectories.Length > 0)
{
foreach (string fullPath in filesOrDirectories)
{
if (Directory.Exists(fullPath))
{
Console.WriteLine(#"{0} is a directory", fullPath);
}
else if (File.Exists(fullPath))
{
Console.WriteLine(#"{0} is a file", fullPath);
}
else
{
Console.WriteLine(#"{0} is not a file and not a directory", fullPath);
}
}
}
}
}
}
private bool CanExecuteDandCommand(object obj)
{
return true;
}
#region INotifyPropertyChanged Implementation
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string name)
{
var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null);
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
#endregion
}
This VM implements a command (called DandCommand) which will be fired by the attached behaviour (remember Step 1?). The 'juicy part' of the VM is the bit which dereferences the drag-and-drop payload. In this particular VM, the code dereferences the data and finds out if it is a file or a directory. It then prints a diagnostic to the console. You can change this part to load images, or internet links, or what-ever can be dropped.
Step 5: Wiring the data context
This is done by different developers in different ways (for industrial apps, lots of people like to use Prism and Unity, but that's ott for a simple how-to like this post). The most straight-forward approach is to change your View to look like this...
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
This code sets the window's data context to your VM so that the binding can take place.
Those steps give you a good starting point for MVVM and drag-and-drop and getting the whole thing to work. The big payback in using MVVM for these things is the clean separation and compartmentalisation that you get. I.e., the VM can be unit-tested without having to instantiate the WPF binding engine.
Related
I am following this great article from Stephen about asynchronous UI, but unfortunately this does not apply to Universal Windows Apps, since CommandManager class is not available.
How can I workaround this limitation?
This is the base type for Async Commands:
public abstract class AsyncCommandBase : IAsyncCommand
{
public abstract bool CanExecute(object parameter);
public abstract Task ExecuteAsync(object parameter);
public async void Execute(object parameter)
{
await ExecuteAsync(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
protected void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
}
As pointed in the comments, this "pattern" shouldn't be used because of it's impact on performance when you have many commands registered.
Any call to CommandManager.InvalidateRequerySuggested() will force WPF to validate every single registered command and it's CanExecute(...) methods.
Instead, just declare the event and only let WPF register to it
public abstract class AsyncCommandBase : IAsyncCommand
{
...
public event EventHandler CanExecuteChanged;
public void RaiseCanExecuteChanged()
{
// C# 6.0, otherwise assign the handler to variable and do null check
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
...
}
Whenever you want to invalidate the command you still just use command.RaiseCanExecuteChanged();. If you want to trigger revalidation of multiple commands, you need to manage it yourself (i.e. creating a CompoundCommand or something similar where you register your commands to groups).
I am really struggling to find a WPF validation pattern that is easily maintainable. I have been doing some web work, and I was really impressed at how easy validation is in AngularJS. So I may have unrealistic expectations of what WPF will do. The solution I have now seems like it has a bunch of garbage. Here is the XAML I have right now. I don't like having to create the DataResource, and it seems far too verbose. Any suggestions?
<local:DataResource x:Key="RequireFcpaGovernmentRelationsText" BindingTarget="{Binding Vendor.RequireFcpaGovernmentRelationsText}" />
<TextBox MaxLength="50" Width="350" HorizontalAlignment="Left">
<Binding Path="Vendor.FcpaGovernmentRelationsText" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:RequiredFieldRule ValidationStep="UpdatedValue" RequireIf="{local:DataResourceBinding DataResource={StaticResource RequireFcpaGovernmentRelationsText}}" RequiredMessage="Please specify government relations."/>
</Binding.ValidationRules>
</Binding>
</TextBox>
Unfortunately, WPF is very verbose by nature. It isn't really fair to compare it to a web technology. The DataResource is needed because of the way that WPF manages the DataContext. We have started doing more and more web project because WPF just doesn't keep up.
This question comes up regularly, and things also change in the .NET world, so let's come up with a current solution that, unlike many snippets here and there, works and is easily maintanable. It will use INotifyDataErrorInfo that's appeared in .NET 4.5.
Make sure you have a base class that you inherit all your data classes from. Make this base class implement INotifyDataErrorInfo:
public abstract class ObjectBase<T> : INotifyDataErrorInfo, INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
private readonly Dictionary<string, List<string>> StoredErrors = new();
protected void OnPropertyChanged(string propertyName) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
if (!string.IsNullOrEmpty(propertyName))
Validate(propertyName);
}
Using INotifyPropertyChanged is not strictly required but you probably want to use that, anyway, and it's easy to combine both.
protected void OnErrorsChanged(string propertyName) =>
ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
public bool HasErrors => StoredErrors.Any();
public IEnumerable GetErrors(string propertyName) => StoredErrors.GetValueOrDefault(propertyName);
protected void AddError(string propertyName, string error) {
if (!StoredErrors.ContainsKey(propertyName))
StoredErrors[propertyName] = new List<string>();
if (!StoredErrors[propertyName].Contains(error)) {
StoredErrors[propertyName].Add(error);
OnErrorsChanged(propertyName);
}
}
protected void ClearErrors(string propertyName) {
if (StoredErrors.ContainsKey(propertyName)) {
StoredErrors.Remove(propertyName);
OnErrorsChanged(propertyName);
}
}
You have two approaches for the actual validation logic, you can select either or even combine them. You can add code to your properties that check for your validation conditions and set the errors if those conditions are not met. Or, you can use attributes on your properties to make it automatic. Only add these extra functions if you plan to use the second approach as well:
public void ValidateAll() {
foreach (var prop in GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static))
Validate(prop.Name);
}
protected void Validate(string propertyName) {
ClearErrors(propertyName);
var prop = GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
var validationAttributes = prop?.GetCustomAttributes(typeof(ValidationAttribute)) ?? new List<Attribute>();
if (validationAttributes.Any()) {
var validationResults = new List<ValidationResult>();
object value = prop.GetValue(this);
if (!Validator.TryValidateProperty(value, new ValidationContext(this, null, null) { MemberName = propertyName }, validationResults)) {
foreach (var attributeValidationResult in validationResults)
AddError(propertyName, attributeValidationResult.ErrorMessage);
}
}
}
That's a bit of a boilerplate all right, but it only needs to go into your base class and the actual data classes will use it very simply:
public class Person : ObjectBase<Person> {
private string name;
[Required(ErrorMessage = "Name is required")]
public string Name {
get => name;
set {
name = value;
OnPropertyChanged(nameof(Name));
}
}
private string address;
public string Address {
get => address;
set {
address = value;
OnPropertyChanged(nameof(Address));
ClearErrors(nameof(Address));
if (address.IsEmpty()) //your own functions
AddError(nameof(Address), "Address is required");
if (address.IsInvalid()) //your own functions
AddError(nameof(Address), "Invalid address");
}
}
You can observe the two approaches here. Either you use attributes like Required, StringLength, etc (WPF has quite a few of them) or you can create your own by inheriting ValidationAttribute and providing an IsValid() override. Or you can use simple conditional logic to set errors. Or you can mix those approaches, both in the same data class, or even in the same property -- whichever you find easier to use and more maintainable.
This is already mostly automatic, but using fields in dialogs might require a little bit more plumbing. Use a CanExecute callback with your OK button command handler:
<CommandBinding Command="{StaticResource DoOk}" Executed="Ok" CanExecute="CanOk" />
private void CanOk(object sender, CanExecuteRoutedEventArgs e) =>
e.CanExecute = !YourData?.HasErrors ?? false;
private void Ok(object sender, ExecutedRoutedEventArgs e) {
YourData.ValidateAll();
if (!YourData.HasErrors) {
DialogResult = true;
}
}
This only allows OK to be enabled if there are no validation errors, and makes sure that the dialog can't be finished even if it's enabled but there are errors (which is usually the case right after opening the dialog but before actually editing the fields).
iv'e got a CompositeCommand exposed globally in my startup project
public static class Commands
{
public static readonly CompositeCommand DiceRolledCommand = new CompositeCommand();
}
in a ControlLibrary referenced by my startup project iv'e got a Control which has a DelegateCommand ,
each instance of this Control has to register it's Command with the globally exposed DiceRolledCommand.
what wold be the best practice of doing so :
here are 3 idea's of which the first 2 i don't like because they are a kinda of hack , where you take some programming component (dp) and alter it's use for your benefit , resulting in poor code and design .
1)
a regular decadency property of type CompositeCommand which will be set with DiceRolledCommand
and on it's CallBack register MyControl's DelegateCommand (OnDiceRolledCommand) .
public class MyControl : Control
{
public DelegateCommand<Tuple<int, int>> OnDiceRolledCommand { get; private set; }
public CompositeCommand GlobalDiceRolledCommand
{
get { return (CompositeCommand)GetValue(GlobalDiceRolledCommandProperty); }
set { SetValue(GlobalDiceRolledCommandProperty, value); }
}
public static readonly DependencyProperty GlobalDiceRolledCommandProperty =
DependencyProperty.Register("GlobalDiceRolledCommand", typeof(CompositeCommand), typeof(MyControl), new UIPropertyMetadata(null,GlobalDiceRolledCommandPropertyChanged));
private static void GlobalDiceRolledCommandPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var myControl= d as MyControl ;
var compoisteCommand = e.NewValue as CompositeCommand;
compoisteCommand.RegisterCommand(myControl.OnDiceRolledCommand);
}
}
<local:MyControl GlobalDiceRolledCommand="{x:Static local:Commands.DiceRolledCommand}"/>
i don't like this approach since it's a kind of manipulation where a Dependency Property is used has a Complex logical setter .
2) i could also do the same as in (1) using a third party class with an attached property which will register the OnDiceRolledCommand in an attached property's CallBack
public static class Commands
{
public static readonly CompositeCommand DiceRolledCommand = new CompositeCommand();
public static ICommand GetRegisterToDiceRolledCommand(DependencyObject obj)
{
return (ICommand)obj.GetValue(RegisterToDiceRolledCommandProperty);
}
public static void SetRegisterToDiceRolledCommand(DependencyObject obj, ICommand value)
{
obj.SetValue(RegisterToDiceRolledCommandProperty, value);
}
public static readonly DependencyProperty RegisterToDiceRolledCommandProperty =
DependencyProperty.RegisterAttached("RegisterToDiceRolledCommand", typeof(ICommand), typeof(Commands), new UIPropertyMetadata(null,OnRegisterToDiceRolledCommandProperty);
private static void OnRegisterToDiceRolledCommandProperty(DependencyObject d , DependencyPropertyChangedEventArgs e)
{
var commandToRegister = e.newValue as DelegateCommand;
DiceRolledCommand.RegisterCommand(commandToRegister );
}
}
<local:MyContorl local:Commands.RegisterToDiceRolledCommand="{Binding OnDiceRolledCommand , RelativeSource={RelativeSource Self}}"/>
i also don't like this approach for the same reason as 1 ..
3) passing the composite command as a parameter to constructor , this approach is better since it keeps
the initializing logic in the constructor where it should be , i just can't figure out how to pass
an argument to a contractor through XAML , i'm not sure if it's even possible .
public class MyControl : Control
{
public MyControl(CompositeCommand globalDiceRolledCommand)
{
.........
globalDiceRolledCommand.Register(OnDiceRolledCommand);
}
}
<local:MyControl ..... >
Some how pass parameters to contractor in order to create the element in XAML
</local:MyControl>
to summarize :
A) any thoughts about (1) and (2) .
B) thoughts of how to accomplish 3 , and if it seems like good design .
C) Any good pattern of accomplishing this scenario.
thanks in advance .
Whenever I use Global Commands like that they are usually defined in either an Infrastructure class library which every library can reference. Or they are defined in a consuming core library that each module could reference directly.
I wrote a lot of this up in a Code Project article
Part 2 here
I use prism v4 and MEF to load my modules. My modules contain a handful of views (MVVM) which are loaded in a ItemsControl/NavigationRegion automatically by MEF.
This works nicely, all items show up in the ItemControl. But I don't like the order in which they show. One module might contain several of the items, so changing the module load order is not enough by itself.
How can I sort the different views in the ItemsControl? Is there any way to sort them by some property?
I use prism V4, MEF and exploration due to attributes like in the StockTraderRI example.
This is actually baked into Prism4. Just apply the ViewSortHintAttribute to your views:
[ViewSortHint("100")]
class FirstView : UserControl { }
[ViewSortHint("200")]
class SecondView : UserControl { }
The default sort comparer on the regions will pick up this attribute and sort the views accordingly. You can put any string into the attribute but I tend to use medium sized numbers that allow me to easily put a new view in between existing ones.
Oh dang, this was way easier than I expected:
You can tell the region manager how to sort the views in a specific region. You just need to provide a compare function to the region.
This example sorts by a very stupid value, the function name:
private static int CompareViews(object x, object y)
{
return String.Compare(x.ToString(), y.ToString());
}
this._regionManager.Regions["MyRegion"].SortComparison = CompareViews;
Of course the region needs to be known to the region manager before you can set the SortComparison. So far the only workaround I found to achieve this was to defer to set the comparison function using the Dispatcher:
private readonly IRegionManager _regionManager;
[ImportingConstructor]
public ShellViewModel(IRegionManager regionManager)
{
this._regionManager = regionManager;
Dispatcher dp = Dispatcher.CurrentDispatcher;
dp.BeginInvoke(DispatcherPriority.ApplicationIdle, new ThreadStart(delegate
{
if (this._regionManager.Regions.ContainsRegionWithName("MyRegion"))
this._regionManager.Regions["MyRegion"].SortComparison = CompareViews;
}));
}
Of course one should use some more useful information than the class name for the sorting order, but this should be easy to solve (I'll just add an interface to all views which might be added to this region which provide a value to sort by).
I'm pretty sure you are looking for the CollectionViewSource. Bea provides some information on how to make use of it in the link.
From an MVVM stance this is how I use the ICollectionView within my ViewModel. The _scriptService.Scripts property is an ObservableCollection<T> getting wrapped in an ICollectionView which is returned to the View. The _view.Filter is being used to filter out items within the ICollection, thus changing the View. Similar to typing 'acc' and seeing all items that begin with 'acc' in your list.
public class ScriptRepositoryViewModel : AViewModel
{
private readonly IUnityContainer _container;
private readonly IScriptService _scriptService;
private readonly IEventAggregator _eventAggregator;
private ICollectionView _view;
public ScriptRepositoryViewModel(IUnityContainer container, IScriptService scriptService, IEventAggregator eventAggregator)
{
_container = container;
_scriptService = scriptService;
_eventAggregator = eventAggregator;
}
public ICollectionView Scripts
{
get
{
if (_view == null)
{
_view = CollectionViewSource.GetDefaultView(_scriptService.Scripts);
_view.Filter = Filter;
}
return _view;
}
}
}
Below is the code which takes care of the filtering, and is coming in via a DelegateCommand within Prism, this resides in the same ViewModel.
#region SearchCommand
public DelegateCommand<object> SearchCommand { get; private set; }
private String _search = String.Empty;
private void Search(object commandArg)
{
_search = commandArg as String;
_view.Refresh();
}
public bool Filter(object arg)
{
bool usingPrefix;
IScript script = arg as IScript;
if (script.FileType == ConvertPrefixToFileType(_search, out usingPrefix))
{
if (_search.Length == 2)
return true;
else
return CheckProperties(script, usingPrefix);
}
else
{
if (usingPrefix)
return false;
else
return CheckProperties(script, usingPrefix);
}
}
With the base functionality in place and making use of the ICollectionView you can apply your sorting as follows....
_view.SortDescriptions.Add(new SortDescription("PropertyName", direction));
More information on the sorting behavior can be found here, as there are some performance thoughts to keep in mind.
You could use either metadata or properties. It depends on whether you have control over the interface or not...
Views are displayed in the order they are added:
RegionManager.RegisterViewWithRegion("ListRegion", typeof(ListView));
RegionManager.RegisterViewWithRegion("ListRegion", typeof(ListView2));
RegionManager.RegisterViewWithRegion("ListRegion", typeof(ListView3));
will look like:
----region--|
| view3 |
| view2 |
| view |
I am writing an WPF MVVM application using Prism. A couple days ago I asked about best practices for managing different views and didn't get a whole lot of feedback. Sense then I have come up with a system that seems to work, but I want to make sure I wont get bit down the road.
I followed the tutorials at http://development-guides.silverbaylabs.org/ to get my shell setup and am confident that my modules are being registered well.
However, nowhere in those tutorials was an example of a view being replaced with a different view within a given region. This in general, seems to be fairly hard to find a good example of. So, today I rolled my own solution to the problem.
Essentially the module has a controller that keeps track of the current view, then when the user wants to switch views, it calls the Regions.Remove command and then the add command to replace it with the current view. It seems like there must be a more elegant solution to just switch between different registered views, but I haven't found it.
All the different possible views for a module are registered with the Unity container when the module is initialized.
The controller and the view switching function follows:
namespace HazardModule
{
public class HazardController : IHazardController
{
private object CurrentView;
public IRegionManager RegionManager { get; set; }
private IUnityContainer _container;
public HazardController(IUnityContainer container)
{
_container = container;
}
/// <summary>
/// Switches the MainRegion view to a different view
/// </summary>
/// <typeparam name="T">The class of the view to switch to</typeparam>
public void SiwthToView<T>()
{
if (CurrentView != null)
{
RegionManager.Regions["MainRegion"].Remove(CurrentView);
}
CurrentView = _container.Resolve<T>();
RegionManager.Regions["MainRegion"].Add(CurrentView);
}
}
}
Any feedback or other better solutions would be appreciated.
I have pretty much the same approach, so does a co-worker who has a bit more Prism experience than myself.
Basically I have a ViewController class which is a property in my ViewModelBase class. This enables all my ViewModels to have access to it in one go. Then in my ViewController class I have a few display management methods. The correctness of this approach is probably debatable but I found it to work quite well in my case
public TView ShowViewInRegion<TView>(string regionName, string viewName, bool removeAllViewsFromRegion)
{
var region = regionManager.Regions[regionName];
var view = region.GetView(viewName) ?? container.Resolve<TView>();
if (removeAllViewsFromRegion)
{
RemoveViewsFromRegion(region);
}
region.Add(view, viewName);
region.Activate(view);
if (regionName == RegionNames.OverlayRegion)
{
eventAggregator.GetEvent<PopupWindowVisibility>().Publish(true);
}
return (TView)view;
}
public void RemoveViewsFromRegion(string regionName)
{
RemoveViewsFromRegion(regionManager.Regions[regionName]);
}
private void RemoveViewsFromRegion(IRegion region)
{
for (int i = 0; i < region.Views.Count() + i; i++)
{
var view = region.Views.ElementAt(0);
region.Remove(view);
}
if (region.Name == RegionNames.OverlayRegion)
{
eventAggregator.GetEvent<PopupWindowVisibility>().Publish(false);
}
}
private static void DeactivateViewsInRegion(IRegion region)
{
for (var i = 0; i < region.ActiveViews.Count(); i++)
{
var view = region.ActiveViews.ElementAt(i);
region.Deactivate(view);
}
}
Then whenever I need to switch out a view or whatever I can just call from my ViewModel
public void ExecuteCreateUserCommand()
{
ViewController.ShowViewInRegion<IUserCreateView>(RegionNames.ContentRegion, ViewNames.UserCreateView, true);
}