Allow us to write Styles like this:
<Style Key="Style1" TargetType="Control">
<Set
Foreground = "#66603a"
Background = "#fff4e4"
BorderBrush = "Red"
BorderThickness = ".5,.5,1.5,1.5"
FontFamily = "Times New Roman"
FontSize= "18"
FontWeight = "Bold"
FontStyle = "Oblique"
Padding = "5"
Margin = "10" />
<Handle MouseEnter ="Control_MouseEnter"/>
</Style>
this is more compact and more readable than:
<Style Key="Style1" TargetType="Control">
<Setter Property="Control.Foreground" Value="#66603a" />
<Setter Property="Control.Background" Value="#fff4e4"/>
<Setter Property="Control.BorderBrush" Value="Red"/>
<Setter Property="Control.BorderThickness" Value=".5,.5,1.5,1.5"/>
<Setter Property="Control.FontFamily" Value="Times New Roman" />
<Setter Property="Control.FontSize" Value="18" />
<Setter Property="Control.FontWeight" Value="Bold" />
<Setter Property="Control.FontStyle" Value="Oblique"/>
<Setter Property="Control.Padding" Value="5" />
<Setter Property="Control.Margin" Value="10" />
<EventSetter Event="MouseEnter" Handler="Control_MouseEnter"/>
</Style>
For complex value, there is a little to enhance:
<Style>
<Set BorderBrush="new()">
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1.0" />
</LinearGradientBrush>
</Set>
</Style>
instead of
<Style>
<Setter Property="BorderBrush" >
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1.0" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
Hi @VBandCS,
great suggestion. You introduced a Set type with this snippet:
<Style Key="Style1" TargetType="Control">
<Set
Foreground = "#66603a"
Background = "#fff4e4"
BorderBrush = "Red"
BorderThickness = ".5,.5,1.5,1.5"
FontFamily = "Times New Roman"
FontSize= "18"
FontWeight = "Bold"
FontStyle = "Oblique"
Padding = "5"
Margin = "10" />
<Handle MouseEnter ="Control_MouseEnter"/>
</Style>
But what if you want to create a style for another FrameworkElement, or a Control subclass? Then you need to find the properties of that other FrameworkElement or Control subclass on the Set type. That would mean there needs to be a Set type for every control type or the properties need to be dynamic somehow. This makes it complicated an I think this was a reason that led to the solution that we have today with Setters that can set any Dependency Property (That doesn't mean that there's not a better way to do it. :))
The second snippet in your first post doesn't need the Control class for the Property attributes, as you've specified it already in the TargetType. You can write it a bit shorter like this:
<Style Key="Style1" TargetType="Control">
<Setter Property="Foreground" Value="#66603a" />
<Setter Property="Background" Value="#fff4e4"/>
<Setter Property="BorderBrush" Value="Red"/>
<Setter Property="BorderThickness" Value=".5,.5,1.5,1.5"/>
<Setter Property="FontFamily" Value="Times New Roman" />
<Setter Property="FontSize" Value="18" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="FontStyle" Value="Oblique"/>
<Setter Property="Padding" Value="5" />
<Setter Property="Margin" Value="10" />
<EventSetter Event="MouseEnter" Handler="Control_MouseEnter"/>
</Style>
Then the next one with the single setter for complex types. Instead of
<Style>
<Setter Property="BorderBrush" >
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1.0" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
you can write
<Style>
<Setter Property="BorderBrush" >
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1.0" />
</LinearGradientBrush>
</Setter>
</Style>
when Issue https://github.com/dotnet/wpf/issues/84 is fixed. The fix will be a one-liner, adding the ContentPropertyAttribute to the Setter class.
Hi @thomasclaudiushuber
There is no need to create a Set type. Parse <Set /> as an xml tag and get its Attr / Value pairs, then create a XAML Setter for each pair, and them to the Style. This can happen in run-time or in the precompiled BAML. This is a straight forward easy solution.
The only work to do, is make the editor / Xaml parser check that each attr written in the Set tag is a property in the TargetType with a valid value, of course with intellisense support.
This should be easier in the absence of the TargetType , where each attr (property) is fully qualified (i.e Control.Foreground = ...).
My aim here is to have a 2-stage Xaml parsing, to allow using some shortcut syntax, that expanded in run-time to the formal Xaml syntax.
Hi @VBAndCs,
ok, I understand. The idea is to extend the XAML Parser, so that it understands the Set tag as a shorthand syntax for the setters.
@thomasclaudiushuber
Exactly. I posted another proposal but in the XAML Slandered repo. In fact I don't know which repo is responsable for Xaml:
https://github.com/Microsoft/xaml-standard/issues/236
I had these ideas while I am working on Vazor. I use the VB XML literal to generate the Razor. I thought about using such technique with XAML somehow, or use xaml styles instead of CSS in Razor, but I found xamle style too verbose, so I thought of this. I add a middle stage between xml and razor, so, I though that this will be helpful in Xaml, especially it is dynamic and can be generated in run-time. I think we need to revise Xaml syntax and make it as shorter as possible.
HI @VBAndCs
I think posting this suggestion into this repo is good, as this is the official WPF repo.
For UWP XAML this repo is the way to go: https://github.com/Microsoft/microsoft-ui-xaml
Thanks,
Thomas
Thank you @VBAndCs and @thomasclaudiushuber for the awesome discussion here! I think both https://github.com/Microsoft/microsoft-ui-xaml and here are a good place to open issues like this, quite a few of us work on both technologies so it will be seen. I personally think any improvements like this should be synchronized across UWP, WPF, and Xamarin.Forms.
It's unfortunate what has happened to https://github.com/Microsoft/xaml-standard repo, although i'm hopeful that we can still align XAML dialects without necessarily creating a "XAML standard".
It seems nobody has mentioned Xamarin.Forms CSS support.
Like WPF, Xamarin.Forms has support for XAML-based styles using resource dictionaries (see e.g. here), but it adds an alternate syntax in the form of (modified) CSS.
This is interesting because:
I would love to see some collaboration so that an evolved form of Xamarin.Forms's CSS can be used in WPF as well.
Most helpful comment
Hi @VBAndCs,
ok, I understand. The idea is to extend the XAML Parser, so that it understands the Set tag as a shorthand syntax for the setters.