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
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 jako HeaderTemplate, akorát HeaderTemplate se nastavuje v XAMLu a Header v C# kódu, kde pouze vytvoříte Content a přiřadíte. Můžete takto třeba programově měnit hlavičku.
- DataTemplate HeaderTemplate { set; get; } – Protože ListView/GridView negeneruje 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 v ItemTemplate – 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ý v DataContext, 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 skrze shift nebo ctrl. 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 DragItemsStarting
- event 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ísto DataContext‘;u místo celé položky chcete vracet v SelectedValuePath.
- 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 { get; } - GroupStyleSelector GroupStyleSelector { set; get; }
- bool IsGrouping { get; }
- ItemContainerGenerator ItemContainerGenerator { get; }
- Style ItemContainerStyle { set; get; }
- StyleSelector Ite mContainerStyleSelector { se t; get; }
- TransitionCollection ItemContainerTransitions { set; get; }
- ItemCollection Items { get; } – Pokud chcete přidávat přímo položky odvozené od ListBoxItem/ListViewItem/GridViewItem. Nicméně já tuto cestu nedoporučuji, viz níže.
- ItemsPanelTemplate ItemsPanel { set; get; } – Šablona prvků, které se načtou z ItemsSource.
- object ItemsSource { set; get; } – Objekt ObservableCollection
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ých DataTemplate podle 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; }
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
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
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
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
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
u
sing 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;
}
}
} </t> </t> </t>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);
}
}
} </Item>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.]]>