V této ukázce budu zkoumat možnosti těchto 3 prvků. V každém který podporuje
Odvození GridView: Object -> DependencyObject -> UIElement -> FrameworkElement -> Control -> ItemsControl -> Selector -> ListViewBase, ISemanticZoomInformation -> GridView
Odvození ListView: Object -> DependencyObject -> UIElement -> FrameworkElement -> Control -> ItemsControl -> Selector -> ListViewBase, ISemanticZoomInformation -> ListView
Odvození ListBox: Object -> DependencyObject -> UIElement -> FrameworkElement -> Control -> ItemsControl -> Selector -> ListBox
GridViewItem, ListViewItem a ListBoxItem mají svou nadřazenou hiearchii úplně stejnou a to sice tuto: Object -> DependencyObject -> UIElement -> FrameworkElement -> Control -> ContentControl -> SelectorItem -> GridViewItem, ListViewItem, ListBoxItem
ListViewBase, ISemanticZoomInformation
Metody navíc oproti třídě Selector:
void CompleteViewChange()void CompleteViewChangeFrom(SemanticZoomLocation, SemanticZoomLocation)void CompleteViewChangeTo(SemanticZoomLocation source, SemanticZoomLocation destination)IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync()void MakeVisible(SemanticZoomLocation item)void ScrollIntoView(object item, ScrollIntoViewAlignment alignment)void ScrollIntoView(object item)void SelectAll()void StartViewChangeFrom(SemanticZoomLocation source, SemanticZoomLocation destination)void StartViewChangeTo(SemanticZoomLocation source, SemanticZoomLocation destination)bool CanDragItems { set; get; }bool CanReorderItems { set; get; }double DataFetchSize { set; get; }- object
Header{ set; get; } – Je to skoro jakoHeaderTemplate, akorátHeaderTemplatese nastavuje v XAMLu aHeaderv C# kódu, kde pouze vytvoříteContenta přiřadíte. Můžete takto třeba programově měnit hlavičku. - DataTemplate
HeaderTemplate{ set; get; } – ProtožeListView/GridViewnegeneruje hlavičku samo, musíte si ji sami vytvořit pokud ji chcete. Opět – nedoporučuji provádět v C# ale v Xamlu. Nezapomeňte dát všem hlavičkám stejnou šířku jako mají sloupce vItemTemplate– toto si musíte hlídat vy, program se o toto nestará. TransitionCollection HeaderTransitions { set; get; }double IncrementalLoadingThreshold { set; get; }IncrementalLoadingTrigger IncrementalLoadingTrigger { set; get; }bool IsActiveView { set; get; }bool IsItemClickEnabled { set; get; }bool IsSwipeEnabled { set; get; }bool IsZoomedInView { set; get; }- IList
SelectedItems{ get; } – Vrací mi vybrané položky, které už pak stačí pouze přetypovat na typ používaný vDataContext, abych mohl používat všechny metody typu. - ListViewSelectionMode
SelectionMode{ set; get; } – Můžete sem dát tyto hodnoty:
None – žádná položka nepůjde vybrat, všechny aktivní položky však budou i nadále aktivní.
Single – Půjde vybrat pouze 1 položka. Pokud kliknete na jinou položku než byla vybrána, přesune se zaškrtnutí na tuto položku. Položku odeberete stejně jako jste ji vybrali – tak že na ni kliknete.
Multiple – Klikem po jedné položce můžete vybrat více položek, po opětovném kliknutí danou položku odeberete. Extended – Můžete vybrat více položek skrzeshiftneboctrl. Pokud máte vybrané položky a kliknete na jinou položku omylem, vybere se vám tato nová položka. SemanticZoom SemanticZoomOwner { set; get; }event DragItemsStartingEventHandler DragItemsStartingevent ItemClickEventHandler ItemClick
Selector
Má navíc oproti třídě ItemsControl tyto chráněné položky:
static bool GetIsSelectionActive(Windows.UI.Xaml.DependencyObject element)bool? IsSynchronizedWithCurrentItem { set; get; }- int
SelectedIndex{ set; get; } – Co vrací – viz. tabulka níže - object
SelectedItem{ set; get; } – Co vrací – viz. tabulka níže - object
SelectedValue{ set; get; } – Co vrací – viz. tabulka níže - string
SelectedValuePath{ set; get; } – Můžete určit, kterou vlastnost místoDataContext‚u místo celé položky chcete vracet vSelectedValuePath. event SelectionChangedEventHandler SelectionChanged
| SelectionMode | SelectedIndex | SelectedItem | SelectedValue | SelectedValuePath |
| None | –1 | null | null | To co mu zadáte, při změně výběru položek se nemění |
| Single | Index zvolené položky | Objekt zvolené položky | Objekt zvolené položky | To co mu zadáte, při změně výběru položek se nemění |
| Multiple | Index první vybrané položky | Objekt první vybrané položky | Objekt první vybrané položky | To co mu zadáte, při změně výběru položek se nemění |
| Extended | Index první vybrané položky | Objekt první vybrané položky | Objekt první vybrané položky | To co mu zadáte, při změně výběru položek se nemění |
ItemsControl
Má navíc oproti třídě Control:
void ClearContainerForItemOverride(DependencyObject element, object item)DependencyObject GetContainerForItemOverride()bool IsItemItsOwnContainerOverride(object item)void PrepareContainerForItemOverride(Windows.UI.Xaml.DependencyObject element, object item)
Má navíc oproti třídě ItemsControl tyto veřejné položky:
static ItemsControl GetItemsOwner(DependencyObject element)static Windows.UI.Xaml.Controls.ItemsControl ItemsControlFromItemContainer(Windows.UI.Xaml.DependencyObject container)string DisplayMemberPath { set; get; }IObservableVector<GroupStyle> GroupStyle { get; }GroupStyleSelector GroupStyleSelector { set; get; }bool IsGrouping { get; }ItemContainerGenerator ItemContainerGenerator { get; }Style ItemContainerStyle { set; get; }StyleSelector ItemContainerStyleSelector { set; get; }TransitionCollection ItemContainerTransitions { set; get; }- ItemCollection
Items{ get; } – Pokud chcete přidávat přímo položky odvozené odListBoxItem/ListViewItem/GridViewItem. Nicméně já tuto cestu nedoporučuji, viz níže. - ItemsPanelTemplate
ItemsPanel{ set; get; } – Šablona prvků, které se načtou zItemsSource. - object
ItemsSource{ set; get; } – ObjektObservableCollection<T>obsahující jednotlivé položky, které si uživatel přeje zobrazit. - DataTemplate
ItemTemplate{ set; get; } – Šablona jedné položky. - DataTemplateSelector
ItemTemplateSelector{ set; get; } – slouží k dynamickému přiřazení různýchDataTemplatepodle různých vlastností. Pro více informací se kouknete na https://stackoverflow.com/questions/2302250/how-to-style-different-items-differently-when-using-data-template-in-xaml/2304265#2304265
Control
O žádné prvky třídy Control se zde nebudeme více zabývat.
FrameworkElement
Z této třídy zde budu zkoumat pouze jednu vlastnost:
- object
DataContext{ set; get; } – objekt, ze kterého se načítají při DataBinding’u jednotlivé vlastnosti.
GridView
Hodí se když:
Zobrazujete věci horizontálně
Nehodí se když:
Potřebujete kompabilitu s klasickými prvky .NETu
Metody navíc oproti třídě ListViewBase: žádné
ListView
Hodí se když:
Zobrazujete věci vertikálně
Nehodí se když:
Potřebujete kompabilitu s klasickými prvky .NETu
Metody navíc oproti třídě ListViewBase: žádné
ListBox
Hodí se když:
Potřebujete zpětnou kompatibilitu
Nehodí se když:
Prvek musí být optimalizovaný pro dotykové ovládání
Metody navíc oproti třídě Selector:
void ScrollIntoView(object item)–void SelectAll()IList<object> SelectedItems { get; }SelectionMode SelectionMode { set; get; }
SelectorItem
Má navíc tyto vlastnosti oproti položce ContentControl:
bool IsSelected { get; set; }
GridViewItem
Má navíc oproti třídě SelectorItem:
ListViewItemTemplateSettings TemplateSettings { get; }
Běžně se od této třídy neodvozuje a nepíše se prezentační kód v C#. Místo toho se pouze vytvoří třída s veřejnými vlastnostmi a dále se namapují tyto vlastnosti pomocí DataBinding’u na šablonu, kterou máte v <GridView.ItemTemplate><DataTemplate> … XAML kód šablony … </DataTemplate></GridView.ItemTemplate>
ListViewItem
Má navíc oproti třídě SelectorItem:
ListViewItemTemplateSettings TemplateSettings { get; }
Běžně se od této třídy neodvozuje a nepíše se prezentační kód v C#. Místo toho se pouze vytvoří třída s veřejnými vlastnostmi a dále se namapují tyto vlastnosti pomocí DataBinding’u na šablonu, kterou máte v <ListView.ItemTemplate><DataTemplate> … XAML kód šablony … </DataTemplate></ListView.ItemTemplate>
ListBoxItem
Má navíc oproti třídě SelectorItem: nic
Běžně se od této třídy neodvozuje a nepíše se prezentační kód v C#. Místo toho se pouze vytvoří třída s veřejnými vlastnostmi a dále se namapují tyto vlastnosti pomocí DataBinding’u na šablonu, kterou máte v <ListBox.ItemTemplate><DataTemplate> … XAML kód šablony … </DataTemplate></ListBox.ItemTemplate>
Třídy dědící od INotifyPropertyChanged
Základem tohoto návodu je implementovat jak ve třídě jedné položky tak u obalující kolekce této třídy.
1) Prvním krokem je tedy definovat třídu položky.
public class Item
{
}2) Vytvořte veřejné vlastnosti a soukromé proměnné, které budou obsahovat data položky.
string header = "";
public string Header
{
get
{
return header;
}
set
{
header = value;
}
}
string description = "";
public string Description
{
get
{
return description;
}
set
{
description = value;
}
}3) Napište si třídu odvozenou od INotifyPropertyChanged, která může vypadat třeba takto:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace W8Learn.DataControls
{
public class NotifyPropertyChanged : INotifyPropertyChanged
{
protected void OnPropertyChanged(object sourceClass, string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(sourceClass, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}4) Odvoďte od této vytvořené třídy vaši třídu položky a doplňte volání OnPropertyChanged() do set‚u každé vlastnosti, na kterou chcete být upozorňován pokud se změní.
public class Item : NotifyPropertyChanged
{
string header = "";
public string Header
{
get
{
return header;
}
set
{
OnPropertyChanged(this, "Header");
header = value;
}
}
string description = "";
public string Description
{
get
{
return description;
}
set
{
OnPropertyChanged(this, "Description");
description = value;
}
}
}5) Vytvořte třídu NotifyPropertyChangedCollection<T>, kde T bude typ položky. Tuto třídu můžete používat při všech kolekcích okolo prvků, které implementují INotifyPropertyChanged.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//-Jmenny prostor System.Reflection se musi importovat rucne
using System.Reflection;
namespace W8Learn.DataControls
{
class NotifyPropertyChangedCollection<T> : NotifyPropertyChanged
{
/// <summary>
/// Musi to byt typ ObservableCollection protoze T implementuje rozhrani INotifyPropertyChanged, a s nim umi pracovat pouze ObservableCollection
/// </summary>
public ObservableCollection<T> Collection = new ObservableCollection<T>();
/// <summary>
/// Nemuze byt staticka, protoze bych musel ke kazdemu volani metody zadavat i typ T
/// </summary>
/// <param name="propertyClass">
/// <param name="propertyName">
/// <returns> </returns>
public string GetPropertyValue(object propertyClass, string propertyName)
{
object o = propertyClass.GetType().GetRuntimeProperty(propertyName).GetValue(propertyClass);
if (o != null)
{
return o.ToString();
}
return string.Empty;
}
}
}6) Napište třídu ItemCollection – obalující třídu na položky. Přidejte do její proměnné kolekce každou položku a každé položce přiřaďte stejný handler události – metodu OnPropertyChanged v této třídě. Je to sice zde zbytečné protože ve W8 se po updatu vlastnosti Text controlu TextBlock se tento nový text nevykreslí, ale v klasické WPF aplikaci by se vykreslil.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace W8Learn.DataControls
{
class ItemCollection : NotifyPropertyChangedCollection<Item>
{
public ItemCollection()
{
for (int i = 0; i < 100; i++)
{
Item item = new Item();
item.Header = "Polozka #" + i.ToString();
item.Description = "";
item.PropertyChanged += item_PropertyChanged;
Collection.Add(item);
}
}
void item_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
OnPropertyChanged(sender, e.PropertyName);
}
}
}7) To je všechno. Nyní už jen u GridView/ListView/ListBox přiřaďte do vlastnosti ItemsSource tuto vlastnost Collection vytvořené třídy ItemCollection a nastavte mód data bindingu u prvků které chcete ukládat do třídy Item na TwoWay.