Giter Site home page Giter Site logo

canton7 / stylet Goto Github PK

View Code? Open in Web Editor NEW
956.0 37.0 141.0 4.09 MB

A very lightweight but powerful ViewModel-First MVVM framework for WPF for .NET Framework and .NET Core, inspired by Caliburn.Micro.

License: MIT License

C# 97.67% Ruby 0.46% PowerShell 1.87%
stylet mvvm mvvm-framework wpf

stylet's Introduction

Project Icon Stylet

NuGet Build status

Introduction

Stylet is a small but powerful ViewModel-first MVVM framework for WPF (.NET 4.5.2+ and .NET Core 3.0+), which allows you to write maintainable and extensible code in a way which is easy to test. Stylet's aims are to:

  • Solve the blockers, niggles, and annoyances which hamper MVVM development without a framework, using simple but powerful concepts.
  • Be obvious to people picking up your project for the first time: there's very little magic
  • Be easy to verify/validate. The LOC count is low, and it comes with a very comprehensive test suite. The code is well-written and well-documented.
  • Be flexible while providing sensible defaults. Almost any part of the framework can be overridden if you wish, but you probably won't want to.

It is inspired by Caliburn.Micro, and shares many of its concepts, but removes most of the magic (replacing it with more powerful alternatives), and simplifies parts considerably by targeting only MVVM, WPF and .NET 4.5.2.

Getting Started

.NET 5.0+ / .NET Core

For .NET Core and .NET 5.0+ projects, the quickest way to get started is by using dotnet new with Stylet's template.

Open a command window where you want to create your new project, and install the Stylet templates using:

dotnet new -i Stylet.Templates

Then create a new .NET 5.0 project with:

dotnet new stylet -n MyStyletProject

(changing MyStyletProject as appropriate).

If you want to create a .NET Core 3.1 project, then:

dotnet new stylet -F netcoreapp3.1 -n MyStyletProject

If you want to set up your project manually, install the Stylet package, then follow the instructions in the Quick Start.

Stylet requires .NET 5.0+ or .NET Core 3.0+.

.NET Framework (<= .NET 4)

For .NET Framework projects, the quickest way to get started is to create a new "WPF Application" project, then install the NuGet package Stylet.Start. This will install Stylet, and set up a simple skeleton project.

See Quick Start for more details.

If you want to set up your project manually, install the Stylet package, then follow the instructions in the Quick Start.

Stylet requires .NET 4.5.2 (Visual Studio 2012 or higher).

Documentation

The Wiki is the documentation source. There's loads of information there - go and have a look, or start with the Quick Start.

Contributing

Contributions are always welcome. If you've got a problem or a question, raise an issue. If you've got code you want to contribute, please read the Contributing guidelines first of all. Create a feature branch off the develop branch, add your changes there, and submit it as a pull request.

stylet's People

Contributors

canton7 avatar keichinger avatar mcavigelli avatar mwdpb avatar pipe01 avatar prime167 avatar taks avatar yaevh avatar yoooi0 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

stylet's Issues

Func Factories cause a StackOverflow exception

First of all, awesome project, thumb up, hope you continue this project.

I'm in a unique situation that I need a child view model to create a new parent view model; the parent view model is just a kind of content container, so it can create child view model dynamically according to the input model info. Constructors look like this:

ParentViewModel(Func<ChildViewModel> childViewModelFactory)
ChildViewModel(Func<ParentViewModel> parentViewModelFactory)

When build it'll cause a StackOverflow. I've read "Circular Dependencies" wiki, but i still do not know how to configure a Func Factory.

Then I try to use Abstract Factories, it can avoid the stackoverflow exception, but I still wonder why Func Factory fails in this scenario.

Thank you in advance

s:View.ActionTarget not working

I'm using the View.ActionTarget redirection in my code, but it doesn't seem to be working.
This is my button:
<Button Content="_Add" s:View.ActionTarget="{Binding NestedViewModel}" Command="{s:Action AddItem}"/>
However, when I click on the button, it says it cannot find the method 'AddItem' on the base ViewModel, not the one that I have indicated in ActionTarget (NestedViewModel).
I set breaks in Stylet.Xaml.View on GetActionTarget() and SetActionTarget(), neither ever appear to be called.

Is there any way for me to debug why it doesn't appear to be setting a different viewmodel to call the action upon?

WindowManager.ShowMessageBox is not showing custom View

I have created a custom MessageBoxViewModel that is implementing IMessageBoxViewModel along with a custom view, MsgBoxViewModel and MsgBoxView respectively. I have set my IoC container (AutoFacBootstrapper) as follows.

builder.RegisterType().As().ExternallyOwned();

However, when I call

_windowManager.ShowMessageBox("test", "test");

It shows up, but not using the view I custom styled. Seems like its using some default view.

StyletIoC: Support default assemblies for auto-binding

Currently the user has to remember to pass an assemblies list into things like AutoBind, ToAllImplementations, etc. This is nasty.

Allow the builder to accept a list of default assemblies to search. Use this in method, unless explicitly overridden.

Unable to validate properties of class within viewmodel

I am simply not able to figure out how to use ValidatingModelBase to validate properties of a class within a viewmodel. As a quick test, I modified the Stylet ModelValidation sample to organize the existing properties under a new User class.

using FluentValidation;

namespace Stylet.Samples.ModelValidation.Pages
{
    public class User
    {
        public string UserName { get; set; }
        public string Email { get; set; }
        public Stringable<int> Age { get; set; }
    }

    public class UserViewModel : Screen
    {
        private IWindowManager windowManager;

        public UserViewModel(IWindowManager windowManager, IModelValidator<UserViewModel> validator) : base(validator)
        {
            this.AutoValidate = false;
            this.windowManager = windowManager;
            this.User = new User();
        }

        public User User { get; set; }

        public void Submit()
        {
            if (this.Validate())
            {
                this.windowManager.ShowMessageBox("Successfully submitted", "success");
            }                
        }        
    }

    public class UserViewModelValidator : AbstractValidator<UserViewModel>
    {
        public UserViewModelValidator()
        {
            RuleFor(x => x.User).SetValidator(new UserValidator());
        }
    }

    public class UserValidator : AbstractValidator<User>
    {
        public UserValidator()
        {
            RuleFor(x => x.UserName).NotEmpty().Length(1, 20);
            RuleFor(x => x.Email).NotEmpty().EmailAddress();
            RuleFor(x => x.Age).Must(x => x.IsValid).WithMessage("{PropertyName} must be a valid number");
            When(x => x.Age.IsValid, () =>
            {
                RuleFor(x => x.Age.Value).GreaterThan(0).WithName("Age");
            });
        }
    }
}

I had to change the databindings in UserView; I tried to bind using the full path as well as by setting a DataContext.

        <Label Grid.Row="0" Grid.Column="0" Target="{Binding ElementName=UserName}">UserName:</Label>
        <TextBox DataContext="{Binding User}" Grid.Row="0" Grid.Column="1" x:Name="UserName" Text="{Binding UserName, UpdateSourceTrigger=PropertyChanged}"/>

        <Label Grid.Row="1" Grid.Column="0" Target="{Binding ElementName=Email}">Email:</Label>
        <TextBox Grid.Row="1" Grid.Column="1" x:Name="Email" Text="{Binding User.Email, UpdateSourceTrigger=PropertyChanged}"/>

        <Label Grid.Row="2" Grid.Column="0" Target="{Binding ElementName=Age}">Age:</Label>
        <TextBox Grid.Row="2" Grid.Column="1" x:Name="Age" Text="{Binding User.Age, UpdateSourceTrigger=PropertyChanged}"/>

It's obvious that the validations are actually working in the viewmodel, as the Success message is only thrown when the form is filled out correctly. However, I simply can't figure out to force the failed validations to trigger the error templates in the view.

Any ideas?

Bind and invoke

Firstly, let me say that this is more of a question or possibly suggested feature than an issue.

Looking at your Bind or BindWeak extension methods, would it make sense to add something like BindAndInvoke or BindWeakAndInvoke, which would not only bind but also invoke the handler once, e.g., to be able to also initialize dependent properties, for example, in one go?

Here is a quick-and-dirty example of what I mean:

        public static IEventBinding BindAndInvoke<TSource, TProperty>(
            this TSource target,
            Expression<Func<TSource, TProperty>> targetSelector,
            EventHandler<PropertyChangedExtendedEventArgs<TProperty>> handler) where TSource : class, INotifyPropertyChanged
        {
            IEventBinding listener = Bind(target, targetSelector, handler);

            string propertyName = targetSelector.NameForProperty();
            Func<TSource, TProperty> propertyAccess = targetSelector.Compile();
            handler(target, new PropertyChangedExtendedEventArgs<TProperty>(propertyName, propertyAccess(target)));

            return listener;
        }

I'm not sure about the best order (e.g., bind first and then invoke once or the other way around). But the idea is to avoid duplication of code, e.g., if you have to essentially repeat what would be done by the handler in addition to establishing the binding.

Stylet.StyletInvalidViewTypeException

Hello. I get this exception says that View doesn't derive from the Window class. But I call .ShowDialog from Conductor.Collection.OneActive derives from Window.
Window's ViewModel:

public class MainViewModel : Conductor<IScreen>.Collection.OneActive
    {
        private ErrorBoxViewModel errorBox;
        private readonly IWindowManager windowManager;

        public MainViewModel(IWindowManager windowManager)
        {
            this.windowManager = windowManager;
        }

        public void ShowError(string message)
        {
            if (errorBox != null)
                errorBox.RequestClose();
            errorBox = new ErrorBoxViewModel(message);
            this.windowManager.ShowDialog(errorBox);
        }
    }

In another view model derives from UserControl I call:
(Conductor as MainViewModel).ShowError("some string");

ErrorBoxViewModel view model derives from UserControl as well:

public class ErrorBoxViewModel : Screen
    {
        public string Message { get; private set; }

        public ErrorBoxViewModel(string message)
        {
            this.Message = message;
        }

        protected override void OnActivate()
        {
            base.OnActivate();
        }

        protected override void OnDeactivate()
        {
            base.OnDeactivate();
        }

        public void CloseWithSuccess()
        {
            this.RequestClose(true);
        }
    }

Any Idea what's wrong?

Conductor<T>.Collection.OneActive closes and disposes the active item twice

I slightly extend Stylet.Samples.TabNavigation.Page2ViewModel class and set the breakpoints in OnClose and Dispose methods

    class Page2ViewModel : Screen, IDisposable
    {
        public Page2ViewModel()
        {
            this.DisplayName = "Page 2";
        }

        protected override void OnClose()
        {
            base.OnClose();
        }

        public void Dispose()
        {
        }
    }

Now if I run the sample application, switch to the second tabsheet, and close the app, then each of my breakpoints is hit twice.

Interesting enough it doesn't seem to happen in StyletUnitTests.ConductorOneActiveTests.ClosingClosesAllItems unit test.

Multiple Screen (with Validator set) tabs in a TabControl: ArgumentNullException in ValidatingModelBase.GetErrors()?

Hello,
first and foremost I would like to thank you for your hard work on this lovely framework: it's lightweight, powerful, with great documentation and basically it's been a lifesaver!

I have been having some issues though while trying to set Screen tabs in a TabControl with the Validator property set (indeed they are needed for CRUD operations in MDI-ish environment). In this situation, the program throws an ArgumentNullException on line 273 of ValidatingModelBase.cs, in the GetErrors() method.

I figure I'm doing something wrong, I'm fairly new to both WPF and MVVM, but I'm really stumped and can't figure it out. If it's an actual bug, it should be easy to reproduce since I seem to have the same problem when I edit the provided Stylet.Sample.ModelValidation sample project like so:

In ShellView.xaml

<Window ...>
    <Grid>
        <TabControl Style="{StaticResource StyletConductorTabControl}" />
    </Grid>
</Window>

In ShellViewModel.cs

public class ShellViewModel : Conductor<IScreen>.Collection.OneActive {
    public ShellViewModel(UserViewModel userViewModel) {
        this.DisplayName = "Stylet.Samples.ModelValidation";
        this.Items.Add(userViewModel);

        this.ActiveItem = userViewModel;
    }
}

Action methods returning Task and exception handling

Hi!

First of all, big thanks for this amazing library. I have just started using it and I really enjoy working with it, it's great!

One thing I love about Stylet is the Command="{stylet:Action Execute}" command binding. I also found it surprising (in a good way) that it handles async methods that return Task.

However, there is a little caveat, that is if the Task is not awaited or disposed, any exceptions it generates will be uncaught.

This leads to problems:

  1. Exceptions are not caught so methods may silently fail to execute.
  2. The whole application will crash after an arbitrary time when GC finalizes the task, causing an unhandled exception.

I haven't had the chance to look at the code yet, but I suppose it's impossible to await tasks in the code that handles execution of actions in Stylet.

One alternative solution would be trailing tasks with .ContinueWith() that will dispose the task on the Dispatcher thread, thus forcing the exception to be shown to the user and instantly close the application.

Dispose get called twice.

Hi, I encoutered another problem with closing.

This also can be reproduced with Stylet.Samples.RedditBrowser sample, but need a bit of change:

  1. Add IDisposable to the SubredditViewModel class.
  2. Implement the Dispose method with any content.
  3. Put a breakpoint inside the Dispose method.
  4. Launch the sample application.
  5. Open a tab, then click the Close button.
  6. The breakpoint will be triggered twice.

Question: Async Actions

Hi,

If I have, say, a button binding via Action to a method returning a Task, is there a way to keep the button disabled as long as the method does not return?
I might add that I'm terribly rusty with WPF, I've just come back after 5-6 years of doing other stuff, so maybe there is a very obvious answer to my question that I've overlooked - in that case sorry.

Thanks a lot for any pointers,
Max

PS: And please let me add that I like your renewed take on MVVM very much!

Newbie question regarding validation

I am a beginner in MVVM and I am not sure which is the best approach:

I have some domain-level models, like User, Product, ProductGroup, etc.
My ViewModels only have one one property which implements INPC, like this:

public ProductGroupViewModel(ProductGroup productGroup) : Screen
        {
            _productGroup = productGroup;
        }

        private ProductGroup _productGroup;
        public ProductGroup ProductGroup
        {
            get => _productGroup;
            set
            {
                _productGroup = value;
                SetAndNotify(ref _productGroup, value);
            }
        }
}

In the View, all the binding is done like this, and this works:
Text="{Binding ProductGroup.Name}"

I also use the same View / ViewModel to create a new ProductGroup and edit an existing one, through the contructor. But in this way, I cannot use Stylet IoC to inject the validator, because my contructing viewmodel does not know how to resolve such a constructor:

public ProductGroupViewModel(ProductGroup productGroup, IModelValidator<ProductGroupViewModel> validator) : base(validator)
        { ... }

What would be the recommended way to solve this issue?
Thanks in advance.

ValidatingModelBase: string[] vs. IEnumerable/IEnumerable<string>

When looking at the IModelValidator interface wouldn't it make more sense to change the return value of methods ValidatePropertyAsync and ValidateAllPropertiesAsync from string[] to IEnumerable<string> for maximum flexibility?

This change wouldn't break existing implementations (except for the method declaration part) but allow them to return any kind of enumerable.

What do you think?

Design-Time Binding support for Views

In other MVVM frameworks such as MVVM Light, there is a ViewModelLocator class which is used to retrieve the ViewModels (View First) which allows you to specify the type of the DataContext to get design time support for all of your bindings.
So far I haven't been able to find such feature in the docs. Is anything like that planned?

AutofacBootstrapper causes multiple Dispose of VMs and Self

I think these registrations are lacking ExternallyOwned specification

protected virtual void DefaultConfigureIoC(ContainerBuilder builder)
{
    var viewManagerConfig = new ViewManagerConfig()
    {
        ViewFactory = this.GetInstance,
        ViewAssemblies = new List<Assembly>() { this.GetType().Assembly }
    };
    builder.RegisterInstance<IViewManager>(new ViewManager(viewManagerConfig));

    builder.RegisterInstance<IWindowManagerConfig>(this); // <<< causes 'this' to Dispose twice
    builder.RegisterType<WindowManager>().As<IWindowManager>().SingleInstance();
    builder.RegisterType<EventAggregator>().As<IEventAggregator>().SingleInstance();
    builder.RegisterType<MessageBoxViewModel>().As<IMessageBoxViewModel>(); // <<< okay, but only as long as MessageBoxViewModel implements no IDisposable
    builder.RegisterAssemblyTypes(this.GetType().Assembly); // <<< both Stylet and Autofac will dispose every ViewModel implementing IDisposable
}

Using CommandBindings with Actions

In my app, prior to using Stylet i used CommandBindings and the 200 or so predefined commands to handle the usual actions like open, save, saveas, etc.

In a window you could define them like this:

<Window.CommandBindings>
    <CommandBinding Command="Open" Executed="OpenFile_Executed" />
    <CommandBinding Command="Close" Executed="CloseApplication_Executed" />
    <CommandBinding Command="Save" Executed="Save_Executed" />
    <CommandBinding Command="SaveAs" Executed="SaveAs_Executed"/>
</Window.CommandBindings>

which then in turn enabled the commands to be used by other elements with intelli-sense support available.
However, if I want to replace the method from the code behind (e.g. OpenFile_Executed) with an action I get an ArgumentException, that Stylet.Xaml.ActionExtension can't be converted to System.Windows.Input.ExecutedRoutedEventHandler

Now the error is pretty clear and the docs are pretty clear how to bind action, but those actions don't have intellisense and I can't access the ExecutedRoutedEventArgs which are passed when I'm just using commands. It would also mean I could use pre-defined keyboard shortcuts like Ctrl+S for things like "Save".

Any way to solve this?

View not updated when property of item in ObservableCollection changes

I have a IObservableCollection which holds a collection of items like this:

public IObservableCollection<ProductGroup> ProductGroups { get; private set; }

When I edit one item in another view, by sending the SelectedProductGroup item to it, when I return in the parent view the DataGrid is not updated, even if the item comes back updated.

Any ideas what I am doing wrong?

Conducting the RootViewModel

I'm trying to isolate a splash screen, login windows and the main application host window into separate windows. My problem is that it seems to look like it was never intended to switch the root viewmodel and thus its window. Or am i missing something?

Binding different views to the same viewmodel

I'm coming back to the desktop from Rob Eisenberg's Aurelia, which is a web port of Caliburn.Micro (but significantly evolved).

In Aurelia, exactly as with Stylet, if no view is supplied in the compositional binding, a naming convention is followed for pairing views to viewmodels. But with Aurelia, we can do something like this (translating into Stylet's idiom):

<DataTemplate>
    <ContentControl s:View.Model="{Binding NavTabViewModel}" s:View="NavTabGroupView"></ContentControl>
</DataTemplate>

or perhaps

<DataTemplate>
    <ContentControl s:View.Model="{Binding NavTabViewModel, View=NavTabGroupView}"></ContentControl>
</DataTemplate>

Often times we wish to bind different views to the same underlying viewmodel (e.g. a calendar with Day, Week, Work-week, and Month views).

Is this possible with Stylet?

Unable to specify AutofacBootstrapper in XAML

Based on your documentation and the Bootstrappers project on GitHub, I have configured the bootstrapper for Autofac (my root viewModel is ShellViewModel):

    public class AutofacBootstrapper<TRootViewModel> : BootstrapperBase where TRootViewModel : class
    {
        ...
    }

In App.xaml, I have this:

<Application x:Class="MyApp"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:MyApp"
             xmlns:s="https://github.com/canton7/Stylet"
             xmlns:stylet="clr-namespace:Stylet;assembly=Stylet"
             xmlns:pages="clr-namespace:MyApp.Pages">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
            <s:ApplicationLoader>
                <s:ApplicationLoader.Bootstrapper>
                        <local:AutofacBootstrapper"/>
                </s:ApplicationLoader.Bootstrapper>
            </s:ApplicationLoader>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Resharper/VS complains that local:AutofacBootstrapper has the incorrect number of parameters. Apparently, the following is necessary:

<stylet:AutofacBootstrapper x:TypeArguments="pages.ShellViewModel"/>

But then, the complaint is that TypeArguments is not allowed in XAML versions below 2009.

What am I missing?

Thank you.

INotifyPropertyChanged.BindWeak usage

from wiki

model.Bind(x => x.StringProperty, (sender, eventArgs) => Debug.WriteLine(String.Format("New value for property {0} on {1} is {2}", eventArgs.PropertyName, sender, eventArgs.NewValue)));
.....
Stylet provides an extension method on INotifyPropertyChanged called BindWeak, which is very similar to Bind, except that it creates a weak binding. The syntax is the same as Bind, so I won't repeat it here.

something like
model.BindWeak (x => x.StringProperty, (sender, eventArgs) ...

But BindWeak uses PropertyChangedEventManager.AddHandler, that add weak reference to WeakPropertyChangedHandler. Аnd without keeping a reference to binding somewhere else the GC will collect it.

Accessing the Autofac container to resolve a named instance

I guess I'm missing something with respect to your embrace of IoC. Normally, with a framework like Stylet I would be able to gain access to the IoC container--it's usually ambient. But it doesn't seem to be ambient in Stylet.

Most of the time, I simply inject my dependencies (property or constructor, depending), as we should. Sometimes, however, obtaining an instance is a more dynamic affair. Consider the following relevant bits of code (I'm using Autofac):

Bootstrapper.cs

protected override void ConfigureIoC(ContainerBuilder builder)
{
    base.ConfigureIoC(builder);
    builder.RegisterType<ContactsModuleViewModel>().Named<IScreen>("contactsModule");
}

ShellViewModel.cs

public class ShellViewModel : Conductor<IScreen>.Collection.OneActive {
public ShellViewModel()
{
    Tabs = new BindableCollection<NavTabViewModel>
    {
        new NavTabViewModel { Group = Directories, Name = "Contacts", GlyphResourceKey = "contactsDirectoryGlyph", ModuleKey = "contactsModule" },
        ...
    };
    ...
}

public void Navigate(object sender, SelectionChangedEventArgs e)
{
    var itemSelected = (NavTabViewModel)e.AddedItems[0];
    var moduleKey = itemSelected.ModuleKey;
    if (!string.IsNullOrEmpty(moduleKey))
    {
        this.ActiveItem = Container.ResolveNamed<IScreen>(moduleKey)   //***Doesn't work, of course***
    }
}
}

The last bit there, where I'm setting this.ActiveItem, is where I'm having trouble. How do I gain access to the container?

Global exception handling in async Action

In Caliburn.Micro it is possible to configure a global exception handler for actions attached to both sync and async methods by intercepting resp. Application.DispatcherUnhandledException and Coroutine.Completed events.

Application.DispatcherUnhandledException trick for sync Actions still works fine in Stylet, but there appears to be no direct counterpart for async Actions. What event would you recommend to use in place of Coroutine.Completed for injecting my own handler for exceptions thrown by async Actions? Thank you!

WindowManager.ShowWindow: How to set window's owner?

I have a ViewModel which shows some popup windows using WindowManager.ShowWindow.
The showing is fine, however when I press ALT+TAB I can see all the popup windows in the window list.

I googled and found that I need to set the showing windows' owner, but the WindowManager seems can not do it.
For now I used an inelegant way: after calling ShowWindow, I published an event through EventAggregator to the owner's view and pass the popup viewmodel as a parameter, and in the view's codebehind, set its owner: ((Window) message.ViewModel.View).Owner = this;.

Yes, I don't like it :(

Validation error indicators are gone after deactivate/activate

I took the standard Stylet.Samples.ModelValidation sample app and just slightly modified its ShellView for Conductor<IScreen>.Collection.OneActive

    public class ShellViewModel : Conductor<IScreen>.Collection.OneActive
    {
        public ShellViewModel(Func<UserViewModel> userViewModelFactory)
        {
            this.DisplayName = "Stylet.Samples.ModelValidation";

            this.Items.Add(userViewModelFactory());
            this.Items.Add(userViewModelFactory());
        }

        protected override void OnActivate()
        {
            base.OnActivate();
            this.ActivateItem(this.Items[0]);
        }
    }
<Window ...>
    <TabControl ItemsSource="{Binding Items}" SelectedItem="{Binding ActiveItem}">
        <TabControl.ContentTemplate>
            <DataTemplate>
                <ContentControl s:View.Model="{Binding}"/>
            </DataTemplate>
        </TabControl.ContentTemplate>
    </TabControl>
</Window>

The initial screen shows up correctly with error indicators. I switch to another tab and the indicators are also there. But when I switch back to the first tab the indicators are gone. Is it a correct behavior? If so then is there a way to force/bring the error indicators back?

Does Stylet have a something like a EventArgsConverter equivalent?

First I would like to say excellent library and to keep up the good work!

As for my question, I am currently using a few third party controls from DevExpress, and a few of the controls pass information through the eventargs. I was wondering if there was a way using Stylet to pass eventargs to the ViewModel or better yet a converter that could convert the eventargs to the type I need.

The DevExpress MVVM framework handles it like this:

 <dxmvvm:Interaction.Triggers>
      <dxmvvm:EventToCommand Command="{Binding YOURCOMMAND}"
                            EventName="THEEVENT"
                            EventArgsConverter="{StaticResource YOUREVENTARGSCONVERTER}"
                            PassEventArgsToCommand="true" />
</dxmvvm:Interaction.Triggers>

Caliburn Micro has:

cm:Message.Attach="[Event LeftSwipe] = [LeftSwipe($source, $eventArgs)]"

In which the $eventArgs are passed to the method on your ViewModel, or you can even create your own $keyword to convert the eventargs to another object (Which I would prefer because I do not want to pass eventargs directly to my ViewModel).

I was just wondering if Stylet had a equivalent?

ViewModels collection for Conductor<IScreen>.Collection.OneActive

Is there any the fastest way to set overrided IModelValidator for all ViewModels and add all ViewModels in some ShellViewModel not like this default way:

public MainViewModel(SomeViewModel tab1, AnotherViewModel tab2, /*etc*/) { //Adding items }

and not with (for every usercontrol viewmodel):

public SomeViewModel(IModelValidator<SomeViewModel> validator) : base(validator) { //smthg }

I mean the situation when there is alot of UserControls in Project.

Binding Windows's Left and Top property doesn't work.

Hi.

I binded a Window's Left and Top properties to a ViewModel, and set WindowStartupLocation="Manual".
However it's doesn't work.

I debugged into this line , and notice that because I binded the Left and Top, their values are always Double.NaN, so WindowManager always set its startup location to center.

In XAML, Resharper/VS complains that ApplicationLoader needs a key (reports as error)

Hello,

(Using VS 2017 and .Net 4.7)

I started with nothing but your Startup NuGet package (and the Stylet NuGet package, of course). App.XAML looks like this:

<Application.Resources>
    <s:ApplicationLoader>
        <s:ApplicationLoader.Bootstrapper>
            <local:Bootstrapper />
        </s:ApplicationLoader.Bootstrapper>
    </s:ApplicationLoader>
</Application.Resources>

There is a red squiggly line under <s:ApplicationLoader>. The complaint is that a key is necessary. When I add one, however, the new complaint is that ApplicationLoader must be a member of a resource dictionary in order to have a key. When I surround the ApplicationLoader with a resource dictionary, that solves the problem: all squigglies disapper. But no window appears when the application runs.

Also, despite the red squiggly (before surrounding with a dictionary), the application still runs. Resharper/VS reports an actual error in the App.XAML file, which is disconcerting.

What's going on here?

Thank you.

ActionExtension for events does not respect guard proeprty

From wiki:

The syntax is exactly the same, although there's no concept of a guard property here.

Why? I want to be able to set MouseLeftButtonUp="{s:Action SomeAction}" and only have the handler actually execute when the guard property lets it. The justification is that I want to be able to use events in the same way I use commands, without having to use some kind of EventToCommand contraption.

Injected type is null in ViewModel

I need a repository injected in my ViewModel, but it comes null. Here is what I do:

in Bootstrapper:

protected override void ConfigureIoC(IStyletIoCBuilder builder)
{
    builder.Bind<IProductGroupRepository>().ToInstance(new ProductGroupRepository(dbConn));
}

and in my ViewModel:

[Inject]
private IProductGroupRepository productGroupRepository;

but it comes null.
Am I doing something wrong?
Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.