# XAML

XAML är ett språk som används i bl.a WPF-program för att beskriva det grafiska gränssnittet. Det liknar delvis HTML och andra XML-släktingar, i det att man skapar element genom att använda start- och sluttagar samt attribut som (ofta) skrivs i starttaggarna.

Installera gärna [NoesisGUI XAML-extension](/mjukvara/visual-studio-code/extensions.md#bonus) i Visual Studio Code för extra hjälp att skriva koden.

## Element

Elementen är UIts byggstenar; de är saker som knappar och textrutor. En del av dem är rena layoutelement, som t.ex. StackPanel som man lägger andra element inuti. Varje element kan olika *attribut*. Ibland kallas elementen också *kontroller*. De kan skrivas med start- och sluttagg eller som självavslutande taggar.

```xml
<TextBlock>Kolla här!</TextBlock>
<Button>Klicka på mig!</Button>
```

```xml
<TextBlock Text="Kolla här!" />
<Button Content="Klicka på mig!" />
```

### Container-element

Ett container-element är ett element som kan innehålla andra element (inklusive container-element).

```xml
<StackPanel Margin="10" Orientation="Horizontal" Spacing="10">
  <TextBlock Text="Text ett" />
  <TextBlock Text="Text två" />
</StackPanel>
```

## Attribut

Det finns många olika attribut tillgängliga för olika element. De kan skrivas antingen inuti starttaggen för elementet eller som child-taggar.

```xml
<TextBlock FontSize="28" Text="Kolla här" />
```

```xml
<TextBlock>
  <TextBlock.FontSize>28</TextBlock.FontSize>
  <TextBlock.Text>Kolla här!</TextBlock.Text>
</TextBlock>
```

### x:Name

Ger elementet ett unikt namn

```xml
<TextBlock x:Name="NameText">Hello</TextBlock>
```

### Text/Content

Get elementet ett innehåll, eller en text. Vissa typer av element har text, men de flesta har Content istället.

```xml
<TextBlock Text="Hello"/>
```

### FontSize

Anger textens storlek.

```xml
<TextBlock FontSize="56" Text="Hello"/>
```

### Margin

Lägger till utrymme kring elementet.

```xml
<TextBlock Margin="10">Hello</TextBlock>
```

## Events

Varje element har ett antal events som kod kan reagera på – t.ex. att en knapp klickas på eller att en kryssruta kryssas i eller ur.

Ett sätt att göra detta är genom att ange event i XAML och sedan ha en matchande metod i fönstrets cs-fil.

{% code title="MainWindow\.xaml" %}

```xml
<Button x:Name="mainButton" Click="OnMainClick" Margin="10">What</Button>
```

{% endcode %}

{% code title="MainWindow\.xaml.cs" %}

```csharp
private void OnMainClick(object sender, RoutedEventArgs e)
{
  MessageBox.Show("Yes");
}
```

{% endcode %}

Genom att analysera **sender** kan man få veta mer – om t.ex. en och samma metod anropas från flera olika objekt kan det vara bra att veta vilket.

```csharp
if (sender is FrameworkElement obj)
{
  MessageBox.Show(obj.Name);
}
```

### Eventbindning i kod

För att helt separera kod från XAML kan man sköta bindningen i C# istället. Det gör också att man kan få flera olika metoder att anropas när en event sker.

Man behöver en referens till objektet; den kan man t.ex. skaffa genom att använda FindName för att hitta objektet man vill lägga till en bindning till, och casta objektet till rätt datatyp.

Sedan utnyttjar man att alla events ligger inlagda i datatypen som [delegates](/grundlaggande/delegates.md).

```csharp
if (FindName("mainButton") is Button button)
{
  button.Click += (object sender, RoutedEventArgs e) => {
    MessageBox.Show("Yes");
  };
}
```

## FindName

En metod som letar igenom alla sub-objekt efter något med angivet `x:Name`. Det man får som resultat är alltid bara ett generellt object, så resultatet behöver castas.

```csharp
if (FindName("mainButton") is Button button)
{
  button.Content = "New text for button";
}
```

## \<Button>

En knapp som man kan klicka på. Har Click-event.

```
<Button Click="ClickTheButton">Click Me</Button>
```

## \<TextBlock>

Ett block som innehåller text.

```
<TextBlock Text="Hello" FontSize="56" />
<TextBlock>Goodbye</TextBlock>
```

## \<StackPanel>

En container-panel som används för att stapla andra element. Orientation avgör i vilken riktning; default är Vertical (elementen staplas uppifrån och ner).

Man kan lägga in vilka element som helst i en StackPanel – inklusive andra StackPanels.

```xml
<StackPanel Margin="10" Orientation="Horizontal" Spacing="10">

</StackPanel>
```

## \<CheckBox>

Kryssrutor, där flera kan vara ikryssade samtidigt. Har eventen Checked och Unchecked.

```xml
<CheckBox>Candle</CheckBox>
<CheckBox>Sword</CheckBox>
<CheckBox>Shield</CheckBox>
```

## \<RadioButton>

Liknande Checkbox, men bara en kan vara ifylld i taget. Bra när användare ska få välja mellan olika saker, och bara får välja en av dem. Har också eventen Checked och Unchecked.

```xml
<RadioButton>Warrior</RadioButton>
<RadioButton>Mage</RadioButton>
<RadioButton>Rogue</RadioButton>
```

## \<Image>

Lägger in en bild! Har attributen Source, Width och Height som kan vara användbara. Source behöver deklareras som en [resursfil](/filhantering/resursfiler.md), eller på annat sätt placeras i samma mapp som exe-filen när programmet kompilerats.

```xml
<Image Width="200" Height="200" Source="cat.jpg" />
```

## \<ListBox>

En lista med text-items dit man kan lägga in nya saker eller ta bort gamla. Det finns C#-metoder för att manipulera listans innehåll, och ett SelectionChanged-event som kan bindas till C#-kod. SelectionMode-attributet används för att göra det möjligt för användare att markera flera saker i listan samtidigt.

{% code title="MainWindow\.xaml" %}

```xml
<ListBox x:Name="list" SelectionMode="Multiple">
  <ListBoxItem>Health Potion</ListBoxItem>
  <ListBoxItem>Broadsword</ListBoxItem>
  <ListBoxItem>Vase with flowers</ListBoxItem>
</ListBox>
```

{% endcode %}

{% code title="MainWindow\.xaml.cs" %}

```csharp
if (FindName("list") is ListBox listBox)
{
  listBox.SelectionChanged += (object sender, SelectionChangedEventArgs e) =>
  {
    MessageBox.Show(listBox.SelectedItems.Count.ToString());
  };
}
```

{% endcode %}

## \<Grid>

Ett container-element som är ett *rutnät* som man kan lägga in andra element i.

I varje grid finns ett RowDefinitions-element och ett ColumnDefinitions-element. I dem finns sedan RowDefinition- och ColumnDefinition-element. Tillsammans bestämmer de vilka rader och kolumner som ska finnas.

Element som läggs in i Grid-elementet kan sedan ges Grid.Row-attribut och Grid.Column-attribut för att bestämma vilken cell (ruta) i rutnätet de ska placeras i.

```xml
<Grid>
  <Grid.RowDefinitions>
    <RowDefinition/>
    <RowDefinition/>
  </Grid.RowDefinitions>
  <Grid.ColumnDefinitions>
    <ColumnDefinition/>
    <ColumnDefinition/>
  </Grid.ColumnDefinitions>
  
  <TextBlock Grid.Row="1" Grid.Column="1">Hello</TextBlock>
</Grid>
```

### \<Grid.Rowdefinitions> / \<Grid.Rowdefinition>

Beskriver ett Grid-elements rader. Genom attributet Height bestäms varje rads höjd, antingen i pixlar eller genom "auto" (expandera så allt får plats) eller "\*" (expanderar för att fylla resterande utrymme).

Har man två rader och deras höjder anges som "5\*" och "3\*" så delas det tillgängliga utrymmet upp mellan dem med proportionerna 5:3.

```xml
<Grid.RowDefinitions>
  <RowDefinition Height="200"/>
  <RowDefinition Height="auto"/>
  <RowDefinition Hwight="*"/>
</Grid.RowDefinitions>
```

### \<Grid.Columndefinitions>

Beskriver ett Grid-elements kolumner. Genom attributet Width bestäms varje kolumns bredd, antingen i pixlar eller genom "auto" (expandera så allt får plats) eller "\*" (expanderar för att fylla resterande utrymme).

Har man två kolumner och deras bredder anges som "5\*" och "3\*" så delas det tillgängliga utrymmet upp mellan dem med proportionerna 5:3.

```xml
<Grid.ColumnDefinitions>
  <ColumnDefinition Width="200"/>
  <ColumnDefinition Width="auto"/>
  <ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
```

### Element i ett grid

När man lägger in andra element i ett grid, så anger man vilken kolumn och vilken rad, alltså vilken position, elementet ska läggas i genom Grid.Row och Grid.Column.

```xml
<TextBlock Grid.Row="0" Grid.Column="1">Hello</TextBlock>
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://csharp.progdocs.se/annat/windows-ui/xaml.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
