Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Resources property to Application #462

Closed
wieslawsoltes opened this issue Mar 2, 2016 · 5 comments
Closed

Add Resources property to Application #462

wieslawsoltes opened this issue Mar 2, 2016 · 5 comments

Comments

@wieslawsoltes
Copy link
Collaborator

Add Resources property to Application so it can behave same as this:

<Application x:Class="Core2D.Perspex.App"
             xmlns="https://github.com/perspex"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Application.Styles>
        <Style>
            <Style.Resources>
                <SolidColorBrush x:Key="BorderBrush">#FFACACAC</SolidColorBrush>
            </Style.Resources>
        </Style>
    </Application.Styles>
</Application>

so it is possible to define resources like this:

<Application x:Class="Core2D.Perspex.App"
             xmlns="https://github.com/perspex"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Application.Resources>
        <SolidColorBrush x:Key="BorderBrush">#FFACACAC</SolidColorBrush>
    </Application.Resources>
</Application>
@grokys
Copy link
Member

grokys commented Mar 3, 2016

Could you explain why exactly you want the second example to be possible? Would it be equivalent to the first example?

Or is the problem that you just don't understand why Resources were moved into Style when they are directly on the Control/Application in other XAML frameworks?

@wieslawsoltes
Copy link
Collaborator Author

I want to have Resources property on Application (and also on UserControl) to define Application wide (and UserControl wide) reusable resources (e.g. brushes) used in Styles and in DataTemplates. This should be separated from Styles and DataTemplates as it can be used everywhere UserControl, Style, DataTemplate etc. Also this are actually the resources the you use and not related to styles only.

And second reason is that this is pattern used in other frameworks, especially in WPF, that I find very convenient and useful.

Finally this can be viewed as syntactic sugar, as you don't have to define style only for resource definition.

Please also tell why it was moved to Style, what was the reasoning.

@grokys
Copy link
Member

grokys commented Mar 3, 2016

Please also tell why it was moved to Style, what was the reasoning.

I'll start by explaining this. It's a long story, so be prepared for a read!

In WPF, styles are added to ResourceDictionary collections, and items in resource dictionaries need a key. The key is either the TargetType for styles that apply to all controls of the specified type, or are explicitly keyed.

When WPF looks up a style, if there is no Style= property specified, it looks for the style by trying to find an element in the resource dictionary with a key == typeof(TheControl), otherwise it uses the key from the Style property. It walks up the tree, searching the resource dictionaries until a match is found, and that's your style. Only a single style can match a control (we're ignoring BasedOn here).

In Perspex we have a CSS-like system where many styles can match a single control, and the order in which they're defined matters. Resource dictionaries are unordered, so immediately we've ruled out a system like WPF's. Now we could make resource dictionaries in Perspex ordered, but that means we'd have to search every object in every resource dictionary for styles. That would be bad for performance.

So instead we store Perspex styles in a Styles collection, which is a) ordered and b) only contains styles. Makes sense?

Now when you want to build a theme in WPF, you create a XAML file containing a ResourceDictionary. But as we've already determined, we can't put styles in a resource dictionary. Instead, we have the XAML file contain a Style (or Styles collection for multiple styles). So where do we put resources in this case? You'll often want to define resources along with your styles for brushes etc, so it makes sense to put the resources under Style, right?

So that's why they're there.

@grokys
Copy link
Member

grokys commented Mar 3, 2016

I'll now address your issue:

I want to have Resources property on Application (and also on UserControl) to define Application wide (and UserControl wide) reusable resources (e.g. brushes) used in Styles and in DataTemplates. This should be separated from Styles and DataTemplates as it can be used everywhere UserControl, Style, DataTemplate etc. Also this are actually the resources the you use and not related to styles only.

Firstly, styles defined in Style.Resources can be used everywhere, they don't just have to be used in Styles. They already should be usable in UserControl, Style, DataTemplate (though there are probably bugs in some of these as I've not tested the feature that thoroughly yet!)

Now let me explain why I think you shouldn't be using them ;)

The reason style resources were introduced was to allow those resources to be overridden for a particular part of the UI. For example, you might want a flyout control in your window to use a dark style while the window uses the light style.

If you just want a named brush for the whole of your application, I'd suggest just exposing a static Brush from code. XAML is actually a really bad place for defining resources that won't change in any part of your UI for these reasons:

  1. The resources have to be parsed
  2. The tree has to be traversed to find them
  3. XAML doesn't handle immutable objects
  4. XAML syntax is really long-winded compared to C#

In general, I agree with this article which says:

VI. Avoid ResourceDictionary

This advice is practically impossible to follow, but do your best. There is a huge cost in constructing ResourceDictionaries, and depending on where you place them, you are probably constructing many more objects than you realize.

@grokys
Copy link
Member

grokys commented Mar 3, 2016

As an addendum: I know there are people who try to define their whole view layer in XAML, and say that using code-behind is bad. I always doubted that this was something to follow, but after implementing Perspex and knowing everything that goes on in the background of a XAML framework - I am positive that they are wrong. It's an incredibly verbose and wasteful (in terms of CPU) way to do things.

You're are not breaking MVVM by writing code in your view layer. Use the tool that makes most sense, and in many many cases that tool is code, not markup.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants