Programowanie w technologii .NET
wykład 2 – posługiwanie się kontrolkami
Własności:
// publiczne zmienne składowe:
class Element {
public string nazwa;
}
// użycie:
Element el = new Element();
el.nazwa = "...";
... = el.nazwa;
// gettery i settery:
class Element {
private string nazwa;
public void setNazwa(string value) {
nazwa = value;
}
public string getNazwa() {
return nazwa;
} }
// użycie:
Element el = new Element();
el.setNazwa("...");
... = el.getNazwa();
// properties:
class Element {
public string nazwa;
public string Nazwa {
set {
nazwa = value;
} get {
return nazwa;
} } }
// użycie:
Element el = new Element();
el.Nazwa = "...";
... = el.Nazwa;
// auto-properties:
class Element {
public string Nazwa { set; get; } }
// użycie:
Element el = new Element();
el.Nazwa = "...";
... = el.Nazwa;
Mechanizm partial class:
class Element {
private int x, y;
protected string nazwa;
public Element(int x, int y) {
this.x = x; this.y = y;
}
public void nazwij(string n) {
nazwa = n;
}
public void przesun(int dx, int dy) {
x += dx; y += dy;
} }
partial class Element {
private int x, y;
public Element(int x, int y) {
this.x = x; this.y = y;
}
public void przesun(int dx, int dy) {
x += dx; y += dy;
} }
partial class Element {
protected string nazwa;
public void nazwij(string n) {
nazwa = n;
} }
Delegacje i zdarzenia:
public delegate void funkcja(string a);
class A {
public void f(string x) {
Console.WriteLine("A.f({0})", x);
} } // ...
A a = new A();
funkcja delegacja = a.f;
// ...
delegacja("test");
public delegate void EventHandler(...);
class Button {
public event EventHandler Click;
protected void mouseButtonDown(...) {
// ...
Click(...);
} }
class MyApp {
MyApp() {
Button btn = new Button();
btn.Click += f;
}
public void f(...) {
// ...
}
„ręczne” tworzenie okna:
public class Window1 : Window {
public Window1() {
InitializeComponent();
}
private void InitializeComponent() {
} }
public class Window1 : Window {
public Window1() { InitializeComponent(); } private void InitializeComponent() {
// tytuł i rozmiar:
this.Width = this.Height = 300;
this.Title = "Okienko";
} }
public class Window1 : Window {
public Window1() { InitializeComponent(); } private void InitializeComponent() {
// tytuł i rozmiar:
this.Width = this.Height = 300;
this.Title = "Okienko";
// przycisk:
button1 = new Button();
button1.Content = "Nie dotykać";
button1.Margin = new Thickness(30);
}
private Button button1;
}
public class Window1 : Window {
public Window1() { InitializeComponent(); } private void InitializeComponent() {
// tytuł i rozmiar:
this.Width = this.Height = 300;
this.Title = "Okienko";
// przycisk:
button1 = new Button();
button1.Content = "Nie dotykać";
button1.Margin = new Thickness(30);
// podpinamy obsługę button1.Click += klik;
}
private Button button1;
private void klik(object sender, RoutedEventArgs e) { button1.Content = "Bzzzzt";
} }
public class Window1 : Window {
public Window1() { InitializeComponent(); } private void InitializeComponent() {
// tytuł i rozmiar:
this.Width = this.Height = 300;
this.Title = "Okienko";
// przycisk:
button1 = new Button();
button1.Content = "Nie dotykać";
button1.Margin = new Thickness(30);
// podpinamy obsługę button1.Click += klik;
// panel na zawartość:
DockPanel panel = new DockPanel();
// przycisk wrzucamy na panel:
panel.AddChild(button1);
// a panel na okno:
this.AddChild(panel);
}
private Button button1;
private void klik(object sender, RoutedEventArgs e) { button1.Content = "Bzzzzt";
} }
public partial class Window1 : Window { private void InitializeComponent() { this.Width = this.Height = 300;
this.Title = "Okienko";
button1 = new Button();
button1.Content = "Nie dotykać";
button1.Margin = new Thickness(30);
button1.Click += klik;
DockPanel panel = new DockPanel();
panel.AddChild(button1);
this.AddChild(panel);
}
private Button button1;
}
public class Window1 : Window { public Window1()
{
InitializeComponent();
}
private void klik(object sender, RoutedEventArgs e) {
button1.Content = "Bzzzzt";
}
<Window x:Class="WpfApplication1.Window1" ...
Width="300" Height="300" Title="Okienko">
<DockPanel>
<Button Margin="30" Name="button1" Click="klik">
Nie dotykać </Button>
</DockPanel>
</Window>
public class Window1 : Window { public Window1()
{
InitializeComponent();
}
private void klik(object sender, RoutedEventArgs e) {
button1.Content = "Bzzzzt";
} }
posługiwanie się własnościami:
<Button Name="btn1">OK</Button>
w kodzie:
btn1.Content = "Not OK";
posługiwanie się zdarzeniami:
<Button Name="btn1" Click="klik">OK</Button>
albo w kodzie:
btn1.Click += new RoutedEventHandler(klik);
lub:
btn1.Click += klik;
i odłączanie:
btn1.Click -= klik;
metoda obsługi zdarzenia:
void klik(object sender, RoutedEventArgs e) { ... }
Content Controls – kontrolki zawartości
Mogą zawierać pojedynczy element. Ten sam mechanizm zagnieżdżania, który pozwalał układać nam elementy w kontenerach, służy do ustawienia zawartości kontrolki.
<StackPanel>
<Button Margin="3" Padding="5">Napis</Button>
<Button Margin="3" Padding="5">
<Image Source="lolface.png" Stretch="None" />
</Button>
<Button Margin="3" Padding="5">
<StackPanel>
<Label Margin="3">Napis i obrazek</Label>
<Image Source="lolface.png" Stretch="None" />
</StackPanel>
</Button>
</StackPanel>
Mają właściwość Content.
uwaga: tylko część elementów umieszczanych na oknie to kontrolki (kontrolki to elementy z którymi użytkownik może wchodzić w interakcję)
Podstawowe własności kontrolek:
Dotyczące rozmieszczenia (Margin, Padding, HorizontalAlignment, VerticalContentAlignment, etc.)
Wybór czcionek:
<WrapPanel Margin="3">
<Label FontFamily="Arial">Arial</Label>
<Label FontFamily="Times New Roman">Times New Roman</Label>
<Label FontFamily="Courier New">Courier New</Label>
<Label FontFamily="Comic Sans MS">Comic Sans MS</Label>
<Label FontSize="24">Size 24</Label>
<Label FontSize="32">Size 36</Label>
<Label FontStyle="Italic">Italic</Label>
<Label FontWeight="Bold">Bold</Label>
<Label FontStyle="Italic" FontWeight="Bold">Italic Bold</Label>
</WrapPanel>
Wybór tła, kolorów, obramowania
<WrapPanel Margin="2">
<Label Foreground="Red">Red</Label>
<Label Foreground="BlueViolet">BlueViolet</Label>
<Label Background="GreenYellow">GreenYellow</Label>
<Label Background="SkyBlue">SkyBlue</Label>
<Label Background="DarkGoldenrod" Foreground="Khaki">...</Label>
<Label BorderBrush="Maroon" BorderThickness="1">Maroon 1</Label>
<Label BorderBrush="Gold" BorderThickness="5">Gold 5</Label>
</WrapPanel>
Albo: <Label Foreground="#FFFF0000">Red</Label>
Background, Foreground są typu Brush, a nie Color – pozwala to na używanie różnego rodzaju wypełnień (gradienty, tekstura, …):
<Label>Red
<Label.Foreground>
<SolidColorBrush Color="Red" />
</Label. Foreground >
</Label>
Ręcznie:
pędzel z koloru:
button1.Background = new SolidColorBrush(Colors.GreenYellow);
z koloru systemowego:
button1.Background = new SolidColorBrush(SystemColors.ControlColor);
pędzle systemowe:
button1.Background = SystemColors.ControlBrush;
z koloru w RGB:
button1.Foreground = new SolidColorBrush(Color.FromRgb(0, 128, 255));
z koloru w ARGB – z wartością Alpha:
button1.Foreground = new SolidColorBrush(Color.FromArgb(128, 0, 128, 255));
Widoczność:
<WrapPanel Margin="2">
<Button>Pierwszy</Button>
<Button Visibility="Hidden">Drugi</Button>
<Button>Trzeci</Button>
</WrapPanel>
Przeźroczystość:
<WrapPanel Background="GreenYellow">
<Button>Pełny</Button>
<Button Opacity="0.5">Opacity</Button>
<Button Background="#80FFFFFF">Kolor</Button>
</WrapPanel>
Dostępność – wyszarzenie:
<WrapPanel>
<Button>Normalny</Button>
<Button IsEnabled="False">Niedostępny</Button>
</WrapPanel>
Przycisk – Button
<StackPanel>
<DockPanel>
<Label Margin="3">Podaj kod:</Label>
<TextBox Margin="3"></TextBox>
</DockPanel>
<WrapPanel HorizontalAlignment="Right">
<Button Margin="3" Padding="15,3" IsDefault="True"
Click="OkClick">OK</Button>
<Button Margin="3" Padding="15,3" IsCancel="True"
Click="CancelClick">Anuluj</Button>
</WrapPanel>
</StackPanel>
private void CancelClick(object sender, RoutedEventArgs e) {
MessageBox.Show("Nacisnąłeś Anuluj");
}
private void OkClick(object sender, RoutedEventArgs e) {
MessageBox.Show("Nacisnąłeś OK");
}
Zdarzenie Click.
Właściwości:
o IsCancel (naciśnięcie Esc automatycznie go uruchomi)
o IsDefault (ma specjalne graficzne oznaczenie, uruchomi go naciśnięcie Enter (o ile nie stoimy na innym przycisku))
o (ale zamknięciem okna musimy zająć się sami)
CheckBox i RadioButton – są szczególnymi typami przycisków.
CheckBox:
właściwość IsChecked – przyjmuje wartość true, false oraz null (stan niezdefiniowany)
właściwość IsThreeState – ustawiona na true oznacza, że użytkownik może wybrać stan niezdefiniowany
<StackPanel>
<CheckBox Margin="3" IsChecked="True">Tak</CheckBox>
<CheckBox Margin="3" IsChecked="False">Nie</CheckBox>
<CheckBox Margin="3" IsChecked="{x:Null}">Może?</CheckBox>
</StackPanel>
RadioButton:
wybór jednego z grupy (na podstawie zawierania elementów w kontenerze)
możliwe definiowanie własnych grup (właściwość GroupName)
<StackPanel>
<RadioButton Margin="3" IsChecked="True">Opcja A</RadioButton>
<RadioButton Margin="3">Opcja B</RadioButton>
<RadioButton Margin="3">Opcja C</RadioButton>
</StackPanel>
GroupBox
Ramka z nagłówkiem, służy do grupowania innych kontrolek
Zawiera pojedynczy element!
<GroupBox Header="Wybierz opcję" Padding="5" Margin="5">
<StackPanel>
<RadioButton Margin="3">Pierwsza</RadioButton>
<RadioButton Margin="3">Druga</RadioButton>
<RadioButton Margin="3">Trzecia</RadioButton>
</StackPanel>
</GroupBox>
W nagłówku możemy umieścić również inne elementy.
<GroupBox Padding="5" Margin="5">
<GroupBox.Header>
<CheckBox Click="adresClick" Name="adresCheck" IsChecked="true">
Adres</CheckBox>
</GroupBox.Header>
<Grid Name="adresGrid">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/> <ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Margin="3">Imię i nazwisko:</Label>
<Label Margin="3" Grid.Row="1">Ulica:</Label>
<Label Margin="3" Grid.Row="2">Kod i miejscowość:</Label>
<TextBox Margin="3" Grid.Column="1" />
<TextBox Margin="3" Grid.Column="1" Grid.Row="1"/>
<TextBox Margin="3" Grid.Column="1" Grid.Row="2"/>
</Grid>
</GroupBox>
private void adres(object sender, RoutedEventArgs e) {
if (adresCheck.IsChecked == true) adresGrid.IsEnabled = true;
else
adresGrid.IsEnabled = false;
}
Przykład praktyczny:
<StackPanel>
<GroupBox Header="Wybierz dodatki" Padding="5" Margin="5">
<StackPanel Name="dodatki" CheckBox.Click="klik">
<CheckBox Margin="3" Tag="Pieczarki">Pieczarki</CheckBox>
<CheckBox Margin="3" Tag="Salami">Salami</CheckBox>
<CheckBox Margin="3" Tag="Oliwki">Oliwki</CheckBox>
<CheckBox Margin="3" Tag="Ser">Ser</CheckBox>
</StackPanel>
</GroupBox>
<Label Margin="3" Name="wybór"/>
</StackPanel>
private void klik(object sender, RoutedEventArgs e) {
string str = "Wybrałeś: ";
foreach (CheckBox cbx in dodatki.Children) {
if(cbx.IsChecked == true) str += cbx.Tag + ", ";
}
wybór.Content = str;
}
Label – etykieta
To również jest kontrolka zawartości
Pozwala na definiowanie mnemoników – skrótów odsyłających do kontrolki
<StackPanel>
<CheckBox Margin="3">Wybór _pierwszy</CheckBox>
<CheckBox Margin="3">Wybór _drugi</CheckBox>
<CheckBox Margin="3">Wybór _trzeci</CheckBox>
<Label Target="pole" Margin="3">D_ane:</Label>
<TextBox Name="pole" Margin="3"></TextBox>
</StackPanel>
ToolTip – podpowiedzi:
Nie reagują na wejście użytkownika
<StackPanel>
...
<Button ToolTip="Naciśnij mnie" Margin="3" Padding="3">
...
</Button>
...
</StackPanel>
Mogą być bardziej złożone:
<Button Margin="3" Padding="3">
<Button.ToolTip>
<StackPanel>
<Label FontWeight="Bold" Background="Blue"
Foreground="White">
Przycisk "Dwa"
</Label>
<TextBlock Padding="10" Width="200"
TextWrapping="WrapWithOverflow">
Opis działania drugiego przycisku zajmuje parę linijek tekstu.
</TextBlock>
<Line Stroke="Black" StrokeThickness="1" X2="200"/>
<Label FontWeight="Bold">F1 - dodatkowa pomoc.</Label>
</StackPanel>
</Button.ToolTip>
Dwa
</Button>
elementy na tooltipie nie reagują na wejście użytkownika!
właściwości kontrolki Tooltip pozwalają ustawić położenie, czas wyświetlania, czas oczekiwania, etc.
Popup: podobne do tooltipa, ale nie znika ani nie pojawia się automatycznie, a jego elementy mogą przyjmować wejście („łapie focusa”)
w XAMLu tylko definiujemy
<Button Click="klik">Opcje</Button>
<Popup Name="opcje" StaysOpen="False" Placement="Mouse"
PopupAnimation="Slide">
<Border BorderBrush="Black" BorderThickness="1"
Background="White">
<StackPanel>
<CheckBox>Opcja 1</CheckBox>
<CheckBox>Opcja 2</CheckBox>
<CheckBox>Opcja 3</CheckBox>
</StackPanel>
</Border>
</Popup>
a otwieramy w kodzie:
private void klik(object sender, RoutedEventArgs e) {
opcje.IsOpen = true;
}
Kursor myszy
właściwość Cursor można ustawić dla każdego elementu
kursory systemowe dostępne jako statyczne właściwości klasy Cursors:
button1.Cursor = Cursors.Wait;
a w XAMLu:
<Button Cursor="Help">Help</Button>
jeśli ustawienia kursora się nakładają (np. okna i kontrolki na nim umieszczonej) –
wybierana jest właściwość bardziej specyficzna (czyli nad kontrolką jest kursor kontrolki, a nad resztą okna – kursor okna)
przeciwdziała temu:
ForceCursor – aby ojciec nadpisał kursora dzieci
inne rozwiązanie – kursor dla każdego elementu każdego okna aplikacji:
Mouse.OverrideCursor = Cursors.Wait;
własne kursory:
this.Cursor = new Cursor(Path.Combine(applicationDir, "mycursor.ani"));
Expander
Ukrywa swoją zawartość, którą użytkownik może rozwinąć.
IsExpanded – sterujemy rozwinięciem/zwinięciem
ExpandDirection – kierunek rozwijania (domyślne Down lub Up, Left, Right)
<StackPanel>
<Expander Header="pierwsza">...</Expander>
<Expander Header="druga">
<StackPanel>
...
</StackPanel>
</Expander>
<Expander Header="trzecia">...</Expander>
</StackPanel>
Kontrolki tekstowe: TextBox Wprowadzanie kilku linijek tekstu:
AcceptsReturn – ustawione na true pozwala na wprowadzanie Enterów
AcceptsTab – podobnie z Tabami
TextWrapping (ustawiona na Wrap lub WrapWithOverflow) – zawijanie zbyt długich wierszy (WrapWithOverflow pozwala wypływać poza kontrolkę zbyt długim liniom, Wrap zawsze łamie tekst)
<TextBox TextWrapping="Wrap" Margin="3">
AlamakotaAlamakota Alamakota</TextBox>
<TextBox TextWrapping="WrapWithOverflow" Margin="3">
AlamakotaAlamakota Alamakota</TextBox>
Ponadto:
MinLines i MaxLines pozwalają na ustawienie rozmiaru kontrolki aby była w stanie wyświetlić zadeklarowaną liczbę linii
LineCount – pozwala sprawdzić faktyczną liczbę linii
VerticalScrollBarVisibility – ustawiając na Visible lub Auto dodajemy pasek przewijania
IsReadOnly – tekst tylko do odczytu (ale pozwala wybrać go i skopiować w odróżnieniu od etykiety)
Text – zawartość tekstowa
Text Selection:
<TextBox Name="box">Ala ma kota. Ala ma kota</TextBox>
<Button Click="klik">zaznacz</Button>
private void klik(object sender, RoutedEventArgs e) {
box.SelectionStart = 5;
box.SelectionLength = 5;
box.SelectedText = "xxx";
box.Focus();
}
Focus() – przejęcie „fokusa”
<DockPanel>
<Label DockPanel.Dock="Left">Dane</Label>
<Button DockPanel.Dock="Right" Click="Clear">Wyczyść</Button>
<TextBox Name="tekst"/>
</DockPanel>
private void Clear(object sender, RoutedEventArgs e) {
tekst.Text = "";
tekst.Focus();
}
Kontrolka, która aktualnie przyjmuje wejście z klawiatury, ma „focusa”.
właściwość Focusable – czy może przyjąć focusa
Przechodzenie Tabem – na podstawie hierarchii zagnieżdżenia.
o Można to zmienić, wybierając własną sekwencję przez ustawienie właści- wości TabIndex (0 – pierwszy, a potem wraz ze wzrostem).
o IsTabStop – jeśli false, to danego elementu nie zwiedzamy Tabem (ale na-
PasswordBox
Password – pozwala pobrać hasło
(hasło przechowywane jest w pamięci w postaci zaszyfrowanej)
<StackPanel>
<DockPanel>
<Label Margin="3">Hasło</Label>
<PasswordBox Name="hasło" Margin="3"/>
</DockPanel>
<Button HorizontalAlignment="Center" Margin="3" Padding="15,3"
Click="OkClick">OK</Button>
</StackPanel>
private void OkClick(object sender, RoutedEventArgs e) {
MessageBox.Show("Twoje hasło to " + hasło.Password + "!");
}
Range-Based Controls (ScrollBar, Slider, ProgressBar)
Przyjmują pewną wartość z ustalonego zakresu
Value (aktualna wartość) – jej zmiana odpala ValueChanged
Maximum i Minimum – dolny i górny zakres Slider:
Orientation – w poziomie czy w pionie?
TickPlacement – None, TopLeft lub BottomRight
TickFrequency – odległość między tickami
IsSnapToTickEnabled – doklejanie do ticków
<Slider Minimum="1" Value="15" Maximum="100" TickFrequency="10"
TickPlacement="TopLeft"/>
Ticks – kolekcja położeń (jeśli np. mają być nieregularnie rozmieszczone)
IsSelectionRangeEnabled – wybór zakresu na ścieżce (użyteczne np. w media playerach) (przy pomocy SelectionStart i SelectionEnd)
<Slider Margin="5" Value="1.5"/>
<Slider Margin="5" Value="1.5" TickFrequency="1"
TickPlacement="BottomRight"/>
<Slider Margin="5" Value="1.5" Ticks="1,2,3,5,8"
TickPlacement="BottomRight"/>
<Slider Margin="5" Value="1.5" TickFrequency="2.5"
TickPlacement="BottomRight" IsSelectionRangeEnabled="True"
SelectionStart="3" SelectionEnd="7"/>
Inny przykład:
<StackPanel Margin="5">
<Slider Margin="5" Minimum="10" Maximum="50" Value="12"
TickFrequency="5" TickPlacement="BottomRight"
ValueChanged="slide"/>
<Label HorizontalAlignment="Center">
To jest test slidera.
</Label>
</StackPanel>
private void slide(object sender,
RoutedPropertyChangedEventArgs<double> e) {
this.FontSize = e.NewValue;
}
ProgressBar
Nie zapewnia interakcji, a jedynie wyświetla jakąś informację dla użytkownika.
Pozwala też na stan nieokreślony (gdy nie wiemy ile czasu potrwa zdarzenie):
<ProgressBar Value="50" Height="18"/>
<ProgressBar Height="18" IsIndeterminate="True" />
Menu
Mamy dostępne dwie kontrolki: Menu (menu aplikacji) i ContextMenu (menu kontekstowe).
Menu:
o Podlega zwyczajnym regułom rozmieszczania elementów (przeważnie jest na szczycie DockPanela lub w pierwszym wierszu Grida).
o Można dodać dowolną liczbę menu.
o Własność IsMainMenu ustawiona na true powoduje, że menu dostanie focusa po naciśnięciu klawisza Alt lub F10.
ContextMenu:
o Nie jest umieszczane w oknie, lecz ustawiane dla konkretnego elementu.
MenuItem
Menu zbudowane jest z elementów typu MenuItem oraz Separator.
MenuItem to rozwijalne podmenu.
Separator to po prostu pozioma linia, nie reagująca na wejście użytkownika.
Menu możemy (teoretycznie) wypełniać dowolnymi elementami (ale lepiej nie przesadzać).
<Menu DockPanel.Dock="Top">
<MenuItem Header="File">
<MenuItem Header="New"/>
<MenuItem Header="Open"/ >
<MenuItem Header="Save"/>
<Separator></Separator>
<MenuItem Header="Exit"/>
</MenuItem>
<MenuItem Header="Edit">
<MenuItem Header="Undo"/>
<MenuItem Header="Redo"/>
<Separator></Separator>
<MenuItem Header="Cut"/>
<MenuItem Header="Copy"/>
<MenuItem Header="Paste"/>
</MenuItem>
</Menu>
MenuItem reaguje na kliknięcie zdarzeniem Click.
Wyświetla: tekst (Header), ikonę (Icon), znacznik wyboru (IsChecked – wybranie dodatkowo IsCheckable kliknięcie zmienia stan wyboru), skrót klawiaturowy (InputGestureText – to jest tylko tekstu skrótu, nie zapewnia to obsługi).
ToolBar i StatusBar
<ToolBar DockPanel.Dock="Top">
<Button>New</Button>
<Button>Open</Button>
<Button>Save</Button>
<Separator/>
<Button>Cut</Button>
<Button>Copy</Button>
<Button>Paste</Button>
</ToolBar>
<StatusBar DockPanel.Dock="Bottom">
<Label>Ready</Label>
</StatusBar>
Items Controls – kontrolki elementów
Pozwalają na wyświetlanie listy wielu elementów.
ListBox
SelectionMode można ustawić na: Multiple (wybieramy kilka klikając na nich) lub Extended (klikając z Ctrl lub Shift)
<ListBox SelectionMode="Multiple">
<ListBoxItem>jeden</ListBoxItem>
<ListBoxItem>dwa</ListBoxItem>
<ListBoxItem>trzy</ListBoxItem>
<ListBoxItem>cztery</ListBoxItem>
</ListBox>
Na liście można umieszczać też inne elementy:
<ListBox>
<ListBoxItem>
<Image Source="uwaga.png"></Image>
</ListBoxItem>
<ListBoxItem>
<Image Source="error.png"></Image>
</ListBoxItem>
</ListBox>
a nawet:
<ListBox>
<StackPanel Orientation="Horizontal">
<Image Source="uwaga.png" Width="30" Height="30"></Image>
<Label VerticalContentAlignment="Center">uwaga</Label>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Image Source="error.png" Width="30" Height="30"></Image>
<Label VerticalContentAlignment="Center">błąd</Label>
</StackPanel>
</ListBox>
pozwala to stworzyć listę wyboru:
<ListBox SelectionMode="Extended" Name="lista"
SelectionChanged="lst_SelChanged"
CheckBox.Click="lst_SelChanged">
<CheckBox>jeden</CheckBox>
<CheckBox>dwa</CheckBox>
<CheckBox>trzy</CheckBox>
<CheckBox>cztery</CheckBox>
</ListBox>
<Label Name="opis"/>
private void lst_SelChanged(object sender, EventArgs e) { StringBuilder str = new StringBuilder();
foreach (CheckBox item in lista.Items) { if (item.IsChecked == true) {
str.Append(item.Content);
str.Append("\r\n");
} }
opis.Content = str.ToString();
ComboBox
działa podobnie jak ListBox, ale ukazuje jedynie jeden wybrany element
<ComboBox IsEditable="True">
<ComboBoxItem>jeden</ComboBoxItem>
<ComboBoxItem>dwa</ComboBoxItem>
<ComboBoxItem>trzy</ComboBoxItem>
<ComboBoxItem>cztery</ComboBoxItem>
</ComboBox >
Właściwość IsEditable ustawiona na true pozwala użytkownikowi wprowadzić własną wartość.
Programistyczny dostęp do listy elementów:
<DockPanel Margin="3">
<ToolBar DockPanel.Dock="Top">
<Button Click="Dodaj">Dodaj</Button>
<Button Click="Usuń">Usuń</Button>
</ToolBar>
<ListBox Margin="3" Name="lista"/>
</DockPanel>
private void Dodaj(object sender, RoutedEventArgs e) {
lista.Items.Add(new ListBoxItem { Content="nowy element" });
}
private void Usuń(object sender, RoutedEventArgs e) {
if(lista.SelectedIndex >= 0)
lista.Items.RemoveAt(lista.SelectedIndex);
}