1

To start I am not familiar with XAML however I know XML/CSS exceptionally well. I've begun helping a friend add some style to their XAML application though very quickly noticed that all of their styling is inline which is a nightmare. Here is a good chunk of their code:

add-type -AssemblyName System.Windows.Controls.Ribbon, PresentationFramework

[xml]$xaml = @"
<Window Height="425" Title="TSD-Essentials" Width="1050" x:Name="Window" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:ribbon="clr-namespace:System.Windows.Controls.Ribbon;assembly=System.Windows.Controls.Ribbon" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:z="http://www.w3.org/1999/xhtml">

 <Grid x:Name="Grid">
  <Grid.RowDefinitions>
   <RowDefinition Height="AUTO"/>
   <RowDefinition Height="AUTO"/>
   <RowDefinition Height="AUTO"/>
   <RowDefinition Height="AUTO"/>
   <RowDefinition Height="AUTO"/>
   <RowDefinition Height="AUTO"/>
  </Grid.RowDefinitions>

  <Grid.ColumnDefinitions>
   <ColumnDefinition Width="75"/>
   <ColumnDefinition Width="155"/>
   <ColumnDefinition Width="AUTO"/>
   <ColumnDefinition Width="AUTO"/>
   <ColumnDefinition Width="AUTO"/>
   <ColumnDefinition Width="AUTO"/>
  </Grid.ColumnDefinitions>

  <Grid.Background>
   <LinearGradientBrush StartPoint=".5,0" EndPoint=".5,1">
    <GradientStop Color="White" Offset="0"/>
    <GradientStop Color="#52618f" Offset="1"/> 
   </LinearGradientBrush>
  </Grid.Background>

  <Label Content="Host Name:" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" Width="80" />
  <TextBox x:Name = "HostName" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Left" Width="150"></TextBox><!--Enter host name-->

  <Label Content="Service Now:" Grid.Column="2" Grid.Row="0" />
  <TextBox Grid.Column="3" Grid.Row="0" Width="175" x:Name = "SNtextBox">Search ServiceNow</TextBox>

    </Grid>
</Window>
"@
$reader = (New-Object System.Xml.XmlNodeReader $xaml)
$window = [Windows.Markup.XamlReader]::Load($reader)
$window.ShowDialog()

Now I've attempted to research and add my own style sheet declarations...

External:

<StyleSheet Source="styles.css" />

Internal:

<StyleSheet>
<![CDATA[
TextBox {background-color: #f0f;}
]]>
</StyleSheet>

However I keep getting error messages. The XAML documentation I come across has various elements such as application however my friend is using window. So I don't know if there is versioning involved or not hence why I pasted a large snippet of the code I've begun to clean up.

Exception calling "Load" with "1" argument(s): "Cannot create unknown type '{http://schemas.microsoft.com/winfx/2006/xaml/presentation}StyleSheet'."

I've been reading through documents like the following though all I end up getting are error messages:

https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/styles/css/#xaml

I'm vaguely aware that this is somehow .NET related (using Windows PowerShell ISE to edit this) though I'm not familiar with this. I simply need to help him get out of inline styling or he'll never get any work done. How can I get a style sheet working and with a simple example of how to change the background-color (or whatever XAML equivalent) to define the background-color of all of the TextBox elements?

John
  • 1
  • 13
  • 98
  • 177
  • I'd strongly consider using Visual Studio to edit XAML instead as the WYSIWYG editor (aka the XAML Designer) is *super* handy for that compared to CSS. – BoltClock Apr 23 '21 at 03:11
  • Also as someone with experience in both, it's illuminating and entertaining to see my suspicions confirmed that XAML would be overwhelming to anyone coming from CSS. I was almost in your position ten years ago, though the fact that I started out with Visual Studio and the designer helped a great deal in getting used to it. – BoltClock Apr 23 '21 at 03:12
  • @BoltClock I'm guessing the Community edition of Visual Studio will be sufficient? I just don't want my friend coding like it's 1994. o.0 – John Apr 23 '21 at 03:15
  • Yep! To be honest, it's not unusual for XAML controls to have presentational attributes on their tags if they're unique (for example, if the main window has styles specific to it, there's not much of a point moving them externally). That said, reusable styles are generally placed in App.xaml and are somewhat more complex than CSS - see https://docs.microsoft.com/en-us/dotnet/desktop/wpf/controls/how-to-create-apply-style?view=netdesktop-5.0 Many of the design principles are familiar, such as – BoltClock Apr 23 '21 at 03:19
  • I'm not familiar with styling XAML *with CSS*, however. From the looks of it, it seems to be a Xamarin feature. I know it's not part of WPF - not natively, anyway. – BoltClock Apr 23 '21 at 03:22

1 Answers1

1

I'm not entirely sure if there is an efficient manner of doing this however this does work. I added the Window.Resources element just after the Window element. Here is the code for that:

<Window [...]><!-- Shown for it's relative position in the code. -->

<Window.Resources>
<Style TargetType="TextBox">
 <Setter Property="Background" Value="#000" />
 <Setter Property="Foreground" Value="#ccc" />
 <Setter Property="HorizontalAlignment" Value="Left" />
 <Setter Property="FontSize" Value="17" />
</Style>
</Window.Resources>

CSS :hover and :focus style appears to be a subset (trying to use minimal code):

<Window.Resources>
 <Style TargetType="TextBox">
  <!-- CSS background-color --> 
  <Setter Property="Background" Value="#000" />

  <Style.Triggers>
   <!-- CSS :hover -->
   <Trigger Property="IsMouseOver" Value="True">
    <Setter Property="BorderBrush" Value="#f0f" />
    <Setter Property="Background" Value="#222" />
    <Setter Property="Foreground" Value="#fff" />
   </Trigger>

   <!-- CSS :focus -->
   <Trigger Property="IsKeyboardFocused" Value="True">
    <Setter Property="BorderBrush" Value="#f0f" />
    <Setter Property="Background" Value="#222" />
    <Setter Property="Foreground" Value="#fff" />
   </Trigger>
  </Style.Triggers>
 </Style>
</Window.Resources>
John
  • 1
  • 13
  • 98
  • 177
  • Looks good - keep in mind that this localizes the styles to TextBoxes in this Window, so they won't apply to other windows. It's good for keeping window-specific styles to their respective windows, without cluttering up App.xaml. – BoltClock Apr 23 '21 at 04:02
  • @BoltClock Thank you! Your resource worked! I'm going through most of the basic stuff and adding `` to make analogies to HTML/CSS so he can reference the insane number of resources for those. I'm also going to try and get `:hover` and `:focus` figured out too and help ensure his application will look slick. – John Apr 23 '21 at 04:22
  • To customize those you'll usually have to edit a control's ControlTemplate and add either triggers or visual states, which is one of the most annoying things about XAML in my opinion - https://learn.microsoft.com/en-us/dotnet/desktop/wpf/controls/how-to-create-apply-template?view=netdesktop-5.0#add-a-trigger – BoltClock Apr 23 '21 at 04:27
  • @BoltClock I figured *that* out (and updated my answer) however I can't seem to get the `border-color` (e.g. `BorderBrush`) to change on focus and hover, suggestions please? – John Apr 23 '21 at 04:42
  • I'd assume that's why you need to edit the ControlTemplate - I haven't touched XAML in a while, on first glance I would've assumed that would work too for a simple TextBox... try asking a separate question? – BoltClock Apr 23 '21 at 04:58