WPF Programowanie w środowisku Windows Wykład 10-1 Zdarzenia i polecenia
Wykład 10-2 Zdarzenia Metoda obsługi zdarzenia może być do niego przypisana w kodzie C# lub w XAML <Image Name="FionaImage" Margin="5" Source="Images/Fiona_67x77.gif" MouseEnter="FionaImage_MouseEnter" MouseLeave="FionaImage_MouseLeave"/> FionaImage.MouseEnter += new MouseEventHandler(FionaImage_MouseEnter); FionaImage.MouseLeave += FionaImage_MouseLeave;
Przekazywanie zdarzeń Wykład 10-3 Z punktu widzenia sposobu przekazywania zdarzeń między kontrolką i jej kontenerem można wyróżnić trzy typy: direct events nie są przekazywane do innych elementów przykłady: MouseEnter, MouseLeave bubbling events w hierarchii elementów przekazywane są "do góry" np. MouseDown jeśli nie zostanie obsłużony w docelowym elemencie, to zdarzenie otrzymuje rodzic tego elementu tunneling events przekazywane są "w dół" np. PreviewKeyDown pozwala w pierwszej kolejności na przechwycenie zdarzenia na poziomie okna WPF używa par komunikatów, np. MouseUp (bubbling) i PreviewMouseUp (tunneling) zdarzenia w tych parach dzielą ten sam obiekt klasy RoutedEventArgs, zatem jeśli w zdarzeniu Preview... w obiekcie zostanie zaznaczona flaga obsłużenia, to drugie zdarzenie nie wystąpi
Wykład 10-4 Klasa RoutedEventArgs Wszystkie zdarzenia w WPF jako argument przyjmują obiekty klas dziedziczących z RoutedEventArgs RoutedEventArgs zawiera następujące właściwości: Source obiekt, który spowodował zdarzenie OriginalSource obiekt, który pierwotnie spowodował zdarzenie zwykle ten sam, co w Source, ale w niektórych przypadkach będzie to obiekt umieszczony głębiej w hierarchii drzewa RoutedEvent obiekt zdarzenia zawierający kilka właściwości opisujących zdarzenie Handled ustawienie na True spowoduje, że nastąpi koniec obsługi zdarzenia (żaden element już go nie otrzyma)
Wykład 10-5 Zdarzenia klawiatury Dla wszystkich elementów dostępne są: PreviewKeyDown, KeyDown, PreviewTextInput, TextInput, PreviewKeyUp, KeyUp Fokus kontrolka może otrzymać fokus tylko jeśli ma ustawioną właściwość Focusable właściwość TabIndex określa kolejność otrzymywania fokusa KeyboardEventArgs.KeyboardDevice.Modifiers pozwala na sprawdzenie stanu klawiszy Shift, Control, Alt i Windows w momencie wystąpienia zdarzenia Statyczne składowe klasy Keyboard pozwalają na sprawdzenie aktualnego stanu klawiszy
Wykład 10-6 Zdarzenia myszy Dla każdego elementu dostępne są następujące zdarzenia: MouseEnter, MouseLeave MouseLeftButtonDown, MouseLeftButtonUp, MouseRightButtonDown, MouseRightButtonUp i odpowiadające im zdarzenia Preview... Klasa Control dodaje: MouseDoubleClick, PreviewMouseDoubleClick Metoda Mouse.Capture pozwala na otrzymywanie przez element zdarzeń myszy także w sytuacji, gdy kursor nie jest położony nad tym elementem Metoda DragDrop.DoDragDrop i składowe obiektu elementu: AllowDrop i Drop pozwalają na obsługę przeciągania myszą
Wykład 10-7 Obsługa poleceń WPF pozwala na zdefiniowanie poleceń i przypisanie do nich kontrolek w taki sposób, by nie było konieczne pisanie wielu metod obsługi zdarzeń WPF automatycznie obsługuje zadanie zmiany stanu kontrolek na niedostępny w przypadku, gdy polecenia mają być niedostępne Model obsługi poleceń w WPF wykorzystuje: obiekty poleceń obiekty będące źródłami poleceń obiekty będące celami poleceń przypisania logiki obsługi do poleceń
Wykład 10-8 Polecenia Polecenie w WPF są tworzone i implementowane z wykorzystaniem interfejsu ICommand ten interfejs zawiera dwie metody: Execute i CanExecute oraz zdarzenie CanExecuteChanged Klasa RoutedCommand jest podstawową implementacją ICommand z obsługą mechanizmów bubbling i tunneling Wbudowane polecenia są zdefiniowane w 5 klasach: MediaCommands, ApplicationCommands, NavigationCommands, ComponentCommands, EditingCommands Własne polecenia mogą być tworzone jako obiekty klasy RoutedCommand lub RoutedUICommand można także stworzyć własne polecenie definiując klasę implementującą interfejs ICommand
Wykład 10-9 Źródła poleceń Źródłem polecenia jest obiekt je wywołujący, np. MenuItem, Button, KeyGesture Źródła poleceń implementują interfejs ICommandSource ten interfejs definiuje 3 właściwości: Command, CommandTarget i CommandParameter ICommandSource jest zaimplementowany w: ButtonBase, MenuItem, Hyperlink i InputBinding InputBinding pozwala na użycie skrótów klawiaturowych (KeyGesture) i gestów myszy (MouseGesture) W większości przypadków obiekt będący źródłem polecenia jest zapisany na zdarzenie CanExecuteChanged
Wykład 10-10 Wiązanie poleceń CommandBinding pozwala na powiązanie polecenia z metodami obsługi jego zdarzeń zawiera właściwość Command, oraz zdarzenia PreviewExecuted, Executed, PreviewCanExecute i CanExecute CommandBinding jest przypisany do określonego obiektu, zwykle okna (często głównego) lub kontrolki w niektórych przypadkach CommandBinding jest przypisany do celu polecenia (np. polecenia związane ze schowkiem dla obiektu TextBox) w większości przypadków najwygodniej jest przypisać do jednego z przodków
<Window.CommandBindings> Programowanie w środowisku Windows <CommandBinding Command="ApplicationCommands.Stop" Executed="Stop_Executed" Commanding CanExecute="Stop_CanExecute"/> Example </Window.CommandBindings> <Window.InputBindings> <KeyBinding Key="S" Modifiers="Control" Command="ApplicationCommands.Stop"/> </Window.InputBindings> <StackPanel> <Menu> <MenuItem Name="stopMenuItem" Header="Stop menu item" Command="ApplicationCommands.Stop" /> </Menu> <Button Name="stopButton" Command="ApplicationCommands.Stop">Stop button</button> <CheckBox Name="allowStopCheckBox">Allow stop</checkbox> </StackPanel> Wykład 10-11 private void Stop_Executed(object sender, ExecutedRoutedEventArgs e) { MessageBox.Show("Stop executed!"); } private void Stop_CanExecute(object sender, CanExecuteRoutedEventArgs e) { e.canexecute = (allowstopcheckbox!= null)? allowstopcheckbox.ischecked.value : false; }
Wykład 10-12 Element docelowy polecenia Celem polecenia jest element, na którym jest wykonywane polecenie W WPF właściwość CommandTarget interfejsu ICommandSource jest wykorzystywana tylko wtedy, gdy obiekt polecenia (implementujący ICommand) jest obiektem RoutedCommand Źródło polecenia może wskazać element docelowy tego polecenia Jeśli nie jest zdefiniowany element docelowy polecenia, to za taki zostanie uznany element posiadający fokus przykład: pozycja menu Wklej zadziała na aktualnie edytowanym elemencie TextBox
WPF Programowanie w środowisku Windows Wykład 10-13 Dane
Zasoby Wykład 10-14 Każdy element pochodzący z klasy FrameworkElement lub FrameworkContentElement ma właściwość Resources ta właściwość jest słownikiem (ResourceDictionary) wszystkich posiadanych przez element zasobów zasoby mogą być definiowane dla dowolnego elementu, ale zwykle ma to miejsce dla obiektu nadrzędnego Window lub Page Każdy zasób w słowniku zasobów musi mieć unikatowy klucz w XAML można użyć atrybutu x:key Zasoby są specjalną formą wiązania danych zoptymalizowaną dla scenariusza, w którym jest bardzo dużo odczytów i bardzo mało modyfikacji wartości
<Window.Resources> Programowanie w środowisku Windows <SolidColorBrush x:key="mybrush" Color="Gold"/> <Style TargetType="Border" x:key="pagebackground"> Resources <Setter Property="Background" Example Value="Blue"/> </Style> <Style TargetType="TextBlock" x:key="titletext"> <Setter Property="DockPanel.Dock" Value="Top"/> <Setter Property="FontSize" Value="18"/> <Setter Property="Foreground" Value="#4E87D4"/> <Setter Property="FontFamily" Value="Trebuchet MS"/> <Setter Property="Margin" Value="0,40,10,10"/> </Style> <Style TargetType="TextBlock" x:key="label"> <Setter Property="DockPanel.Dock" Value="Right"/> <Setter Property="FontSize" Value="8"/> <Setter Property="Foreground" Value="{StaticResource MyBrush}"/> <Setter Property="FontFamily" Value="Arial"/> </Style> </Window.Resources> <StackPanel> <Border Style="{StaticResource PageBackground}"> <DockPanel> <TextBlock Style="{StaticResource TitleText}">Title</TextBlock> <TextBlock Style="{StaticResource Label}">Label</TextBlock> <TextBlock DockPanel.Dock="Top" HorizontalAlignment="Left" FontSize="36" Foreground="{StaticResource MyBrush}" Text="Text" Margin="20" /> <Button DockPanel.Dock="Top" HorizontalAlignment="Left" Height="30" Background="{StaticResource MyBrush}" Margin="40">Button</Button> </DockPanel> Krzysztof </Border> Mossakowski </StackPanel> Wykład 10-15
Wykład 10-16 Zasoby c.d. Zasoby można także definiować na poziomie aplikacji, wtedy są dostępne dla wszystkie okien lub stron <Application In such x:class="wpfapplication1.app" case, they are available for all windows, pages, etc. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="Data/Resources.xaml" Startup="Application_Startup" Exit="Application_Exit"> <Application.Resources> <SolidColorBrush x:key="mainbrush">black</solidcolorbrush> </Application.Resources> </Application> <Window [...]> <Ellipse DockPanel.Dock="Top" HorizontalAlignment="Left" Width="100" Height="100" Fill="{StaticResource MainBrush}" Margin="40" /> </Window>
Dynamiczne zasoby Dynamiczne zasoby mogą być modyfikowane podczas wykonania programu <Ellipse DockPanel.Dock="Top" HorizontalAlignment="Left" Width="100" Height="100" Margin="40" Fill="{DynamicResource MainBrush}" MouseDown="Ellipse_MouseDown" /> Wykład 10-17 private void Ellipse_MouseDown(object sender, MouseButtonEventArgs e) { Application.Current.Resources["MainBrush"] = new SolidColorBrush(Colors.Blue); } Dynamiczne wiązanie w kodzie można osiągnąć wykorzystując metodę SetResourceReference button1.setresourcereference(button.backgroundproperty,"mainbrush"); Użycie dynamicznych zasobów jest mniej wydajne w porównaniu ze statycznymi zasobami
Wykład 10-18 Wiązanie danych Wiązanie danych pozwala na określenie, jakie wartości wskazanych właściwości docelowego obiektu mają być ustawione na podstawie danych pobranych z jakiegoś obiektu właściwość musi być typu dependency property zwykle jest to właściwość jakiegoś elementu przykłady obiektów źródłowych: inny element, własna struktura danych, dane z obiektów ADO.NET lub LINQ
Przykład wiązania danych z elementu Wykład 10-19 <StackPanel> <StackPanel.Resources> <x:array x:key="availablecolors" x:type="{x:type Color}"> <x:static Member="Colors.Black"/> <x:static Member="Colors.Red"/> <x:static Member="Colors.Green"/> <x:static Member="Colors.Blue"/> </x:array> <CollectionViewSource Source="{Binding Source={x:Static Fonts.SystemFontFamilies}}" x:key="availablefontfamilies"/> </StackPanel.Resources> <ComboBox Name="fontFamilyComboBox" ItemsSource="{Binding Source={StaticResource AvailableFontFamilies}}" SelectedIndex="0" IsReadOnly="True"> <ComboBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding}" FontFamily="{Binding}"/> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox>
<ComboBox Programowanie Name="colorsComboBox" w środowisku Windows ItemsSource="{StaticResource AvailableColors}" SelectedIndex="2" IsReadOnly="True"> Element-To-Element Binding Example <ComboBox.ItemTemplate> <DataTemplate> <Border x:name="selecteditemborder" MinHeight="16" MinWidth="100" > <Border.Background> <SolidColorBrush Color="{Binding}"/> </Border.Background> </Border> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox> <TextBox Name="textBox">Something</TextBox> <Slider Name="sizeSlider" TickFrequency="1" TickPlacement="TopLeft" Minimum="1" Maximum="96" Value="10"/> Wykład 10-20 <TextBlock Text="{Binding ElementName=textBox, Path=Text}" FontSize="{Binding ElementName=sizeSlider, Path=Value}" FontFamily= "{Binding ElementName=fontFamilyComboBox, Path=SelectedItem}" > <TextBlock.Foreground> <SolidColorBrush Color= "{Binding ElementName=colorsComboBox, Path=SelectedItem}" /> </TextBlock.Foreground> </TextBlock> </StackPanel>
Wykład 10-21 Błędy wiązania danych WPF nie zgłasza wyjątków w przypadku problemów z powiązaniem jeśli nie ma właściwości, to po prostu nic się nie dzieje Jedyną informacją o problemach jest wpis na wyjściu debugowym (np. w oknie Output Visual Studio) System.Windows.Data Error: 22 : Cannot convert '#FF008000' from type 'Color' to type 'System.Windows.Media.Brush' for 'en-us' culture with default conversions; consider using Converter property of Binding. NotSupportedException: 'System.NotSupportedException: BrushConverter cannot convert from System.Windows.Media.Color. at System.ComponentModel.TypeConverter.GetConvertFromException(Object value) at System.ComponentModel.TypeConverter.ConvertFrom(ITypeDescriptorContext at System.Windows.Media.BrushConverter.ConvertFrom(ITypeDescriptorContext at MS.Internal.Data.DefaultValueConverter.ConvertHelper(Object o, Type Można zmienić wygląd źródłowego elementu powiadamiając w tej sposób o problemie
Wykład 10-22 Tworzenie wiązania w kodzie Binding binding = new Binding(); binding.source = sizeslider; binding.path = new PropertyPath("Value"); previewtextblock.setbinding(fontsizeproperty, binding); Wiązanie można usunąć za pomocą jednej z dwóch statycznych metod klasy BindingOperations: ClearBinding lub ClearAllBindings te metody są w stanie także usunąć wiązanie zdefiniowane w XAML Sugerowane jest wykorzystanie XAML do tworzenia powiązań
Wykład 10-23 Kierunek powiązania Wyliczenie BindingMode definiuje 5 typów powiązań: OneWay element docelowy jest uaktualniany stosownie do zmian w źródłowym obiekcie OneWayToSource obiekt źródłowy jest uaktualniany stosownie do zmian w docelowym elemencie TwoWay uaktualnianie źródło <-> cel jest dwukierunkowe OneTime dane pobierane są tylko raz, późniejsze modyfikacje źródła są ignorowane Default: TwoWay dla właściwości, które mogą być modyfikowane przez użytkownika, np. TextBox.Text OneWay w pozostałych przypadkach
Wykład 10-24 Wiązanie do obiektów innych niż elementy Jako źródło wiązania danych może zostać wykorzystana dowolna publiczna składowa dowolnego obiektu to musi być właściwość (property), publiczna składowa (field) nie może być użyta W przypadku docelowych obiektów nie będących elementami można wykorzystać następujące właściwości: Source RelativeSource DataContext
Wykład 10-25 Właściwość Source Właściwość Source określa źródłowy obiekt i właściwość wiązania Można wykorzystać statyczne obiekty <TextBlock Text="{Binding Source={x:Static SystemFonts.IconFontFamily}}" /> Można także wykorzystać zasoby <StackPanel.Resources> <FontFamily x:key="specialfont">trebuchet MS</FontFamily> </StackPanel.Resources> <TextBlock Text="{Binding Source={StaticResource SpecialFont}}" />
Wykład 10-26 Właściwość RelativeSource Używając właściwości RelativeSource jako źródło danych wiązania można wskazać obiekt będący w relacji z celem do definicji wiązania można wykorzystać jeden ze sposobów przedstawionych w przykładach <TextBlock> <TextBlock.Text> <Binding Path="Title"> <Binding.RelativeSource> <RelativeSource Mode="FindAncestor" AncestorType="{x:Type Window}" /> </Binding.RelativeSource> </Binding> </TextBlock.Text> </TextBlock> <TextBlock Text="{Binding Path=Title, RelativeSource= {RelativeSource FindAncestor, AncestorType={x:Type Window}}}"> </TextBlock>
Wykład 10-27 RelativeSourceMode Dostępne są 4 możliwości dla wykorzystania RelativeSources: Self wiązanie w obrębie jednego elementu FindAncestor wiązanie do nadrzędnego elementu konieczne jest podanie AncestorType można podać także AncestorLevel PreviousData wiązanie do poprzedniej porcji danych wykorzystywane przy dowiązywaniu do listy danych TemplatedParent wiązanie z wzorca do elementu działa tylko dla wiązania zdefiniowanego wewnątrz wzorca kontrolki lub wzorca danych
Właściwość DataContext Jeśli w definicji wiązania nie jest określona właściwość Source, to jako źródło danych zostanie wzięty obiekt wskazany we właściwości DataContext jeśli jest nieokreślona, to WPF szuka wyżej w drzewie do znalezienia pierwszej określonej <StackPanel> <TextBlock Text="{Binding Source={x:Static SystemFonts.IconFontFamily}, Path=Source}"/> <TextBlock Text="{Binding Source={x:Static SystemFonts.IconFontFamily}, Path=LineSpacing}"/> <TextBlock Text="{Binding Source={x:Static SystemFonts.IconFontFamily}, Path=FamilyTypefaces[0].Style}"/> <TextBlock Text="{Binding Source={x:Static SystemFonts.IconFontFamily}, Path=FamilyTypefaces[0].Weight}"/> </StackPanel> <StackPanel DataContext="{x:Static SystemFonts.IconFontFamily}"> <TextBlock Text="{Binding Path=Source}"/> <TextBlock Text="{Binding Path=LineSpacing}"/> <TextBlock Text="{Binding Path=FamilyTypefaces[0].Style}"/> <TextBlock Text="{Binding Path=FamilyTypefaces[0].Weight}"/> </StackPanel> Wykład 10-28
Wiązanie do kolekcji obiektów Wszystkie obiekty klas dziedziczących z ItemsControl udostępniają trzy właściwości: ItemsSource kolekcja źródłowych danych DisplayMemberPath właściwość źródłowych obiektów, która zostanie użyta ItemTemplate wzorzec danych, który zostanie wykorzystany do stworzenia prezentacji danych Wykład 10-29 <Window x:class="wpfapplication1.data.bindingtocollection" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:src="clr-namespace:wpfapplication1" Title="BindingToCollection" Height="300" Width="300"> <StackPanel> <StackPanel.Resources> <src:customers x:key="customers"/> </StackPanel.Resources> <ListBox ItemsSource="{StaticResource customers}" DisplayMemberPath="LastName"/> </StackPanel> </Window>
Wykład 10-30 ObservableCollection<T> ObservableCollection<T> to klasa będącą kolekcją danych implementującą INotifyCollectionChanged ten interfejs zawiera zdarzenie CollectionChanged, które powinno być wywoływane w przypadku modyfikacji danych zawartych w kolekcji
Wykład 10-31 Konwersja danych Konwerter wartości jest odpowiedzialny za konwersję danych źródłowych tuż przed ich wyświetlenie w docelowym elemencie w dwukierunkowym wiązaniu jest także odpowiedzialny za konwersję wartości przed jej zapisaniem w źródle danych Konwertery wartości mogą być wykorzystane do: formatowania danych do postaci napisów tworzenia obiektów określonych typów
Wykład 10-32 Wykorzystanie konwertera wartości 1. Utworzyć klasę implementującą interfejs IValueConverter 2. Dodać do klasy atrybut ValueConversion i określić w nim typy danych 3. Zaimplementować metody konwersji Convert i ConvertBack <Window x:class="wpfapplication1.data.dateconverterexample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:src="clr-namespace:wpfapplication1" xmlns:sys="clr-namespace:system;assembly=mscorlib"> <Grid> <Grid.Resources> <src:dateconverter x:key="dateconverter"/> </Grid.Resources> <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Source={x:Static sys:datetime.now}, Converter={StaticResource dateconverter}}"/> </Grid> </Window>
Przykład konwertera wartości Wykład 10-33 [ValueConversion(typeof(DateTime), typeof(string))] public class DateConverter : IValueConverter { public object Convert(object value, Type targettype, object parameter, CultureInfo culture) { DateTime date = (DateTime)value; return date.toshortdatestring(); } } public object ConvertBack(object value, Type targettype, object parameter, CultureInfo culture) { string strvalue = value.tostring(); DateTime resultdatetime; if (DateTime.TryParse(strValue, out resultdatetime)) { return resultdatetime; } return value; }
Sprawdzanie poprawności danych Wykład 10-34 W WPF wbudowane są możliwości sprawdzania poprawności danych Można wykorzystać jedną z dwóch technik sprawdzania poprawności danych: rzucić wyjątek z kodu ustawiającego wartość właściwości domyślnie WPF ignoruje wszystkie wyjątki rzucane podczas ustawiania wartości właściwości można wykorzystać ExceptionValidationRule do wskazania, że wyjątki nie powinny być ignorowane zdefiniować sprawdzanie poprawności danych na poziomie definicji łączenia danych to pozwala na użycie tej samej logiki sprawdzenia poprawności niezależnie od kontrolki wykorzystanej do wprowadzenia danych
Przykład sprawdzania poprawności Wykład 10-35 <TextBox Grid.Column="1" Grid.Row="1" Width="200" Margin="5,5,50,5" Style="{StaticResource highlightvalidationerror}" Validation.ErrorTemplate="{StaticResource validationtemplate}"> <TextBox.Text> <Binding Path="SomeDate" UpdateSourceTrigger="PropertyChanged"> <Binding.ValidationRules> <ExceptionValidationRule /> </Binding.ValidationRules> </Binding> </TextBox.Text> </TextBox> http://www.thejoyofcode.com/reason_10._validation.aspx
<ControlTemplate Programowanie x:key="validationtemplate"> w środowisku Windows Wykład 10-36 <DockPanel> <Border Name="validationBorder" BorderBrush="Red" BorderThickness="2" Validation Padding="1" Example CornerRadius="3"> cont. <Border.Resources> <Storyboard x:key="_blink"> <ColorAnimationUsingKeyFrames AutoReverse="True" BeginTime="00:00:00" Storyboard.TargetName="validationBorder" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" RepeatBehavior="Forever"> <SplineColorKeyFrame KeyTime="00:00:00.5" Value="#00FF0000"/> </ColorAnimationUsingKeyFrames> </Storyboard> </Border.Resources> <Border.Triggers> [...] </Border.Triggers> <AdornedElementPlaceholder/> </Border> <src:exclamation Width="25" Height="25" /> </DockPanel> </ControlTemplate> <Style x:key="highlightvalidationerror" > <Style.Triggers> <Trigger Property="Validation.HasError" Value="True"> <Setter Property="TextBox.Background" Value="Pink" /> <Setter Property="TextBox.ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}"/> </Trigger> </Style.Triggers> </Style>
Wykład 10-37 Wzorce danych Wzorzec danych definiuje sposób, w jaki mają być wyświetlane dane pobrane przez wiązanie Dwa typy kontrolek obsługują wzorce danych: kontrolki wyświetlające pojedynczą zawartość mogą wykorzystać wzorzec danych zdefiniowany we właściwości ContentTemplate kontrolki wyświetlające listę wartości wykorzystują właściwość ItemTemplate <ListBox Name="personsListBox"> <ListBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Path=FirstName}"></TextBlock> </DataTemplate> </ListBox.ItemTemplate> </ListBox>