WPF: Vázání dat na property

Data binding koncept ve WPF frameworku je postaven na skutečnosti, která by se dala vyjádřit jednoduchou větou – cokoliv se dá jednoduše provázat s čímkoliv. A to jak jednosměrně, tak i obousměrně.

Díky tomuto konceptu může být prezentační logika striktně oddělena od aplikační logiky a od dat. Koncept WPF je postaven na návrhovém vzoru MVVM a umožňuje vyvíjet aplikační front-end vývojářům, kteří nepotřebují znát aplikační pozadí ani způsob uložení a tahání dat.

Vázat data lze jak na business objekty View-Model vrstvy, ale lze vázat i na jiné prvky v prezentační vrstvě. Já teď ukážu vázání na property aktuální třídy, což je problém, který jsem před nedávnem řešil.

Vezměme si následující případ…
Uživatel v nějakém datagridu klikne na položku a očekává, že se otevře nějaké dialogové okno, kde bude detail daného záznamu se všemi položkami, on bude moci ty položky upravit, uložit a zavřít dialog. Jak na to?

Náš DataGrid máme nabindovaný na nějaký objekt typu List<T>, nebo IObservable<T>, a to pomocí CollectionViewSource komponenty. Nějak takhle…

DataGrid binding
XHTML
1
2
3
4
5
6
7
8
<Window.Resources>
<ResourceDictionary>
<Data:MyRecords x:Key="DataSource"/>
<CollectionViewSource x:Key="DataCollection" Source="{StaticResource DataSource}"/>
</ResourceDictionary>
</Window.Resources>
<DataGrid Name="GridData"
ItemsSource="{Binding Source={StaticResource DataCollection}}">

V každém řádku je tlačítko, kterým vyvoláme otevření dialogu a předáme mu přes property set daný záznam.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private void EditDetail_Click(object sender, RoutedEventArgs e)
{
var dataCollection = this.FindResource("DataCollection") as CollectionViewSource;
var data = dataCollection.Source as IMyRecords;
var record = (IMyRecord)((FrameworkElement)sender).DataContext;
var form = new MyDetailForm();
form.Owner = (Window)this.Parent;
form.Record = record as MyRecord;
form.ShowDialog();
if (form.DialogResult == true)
{
record = (IMyRecord)form.Record;
data.UpdateRecord(record);
ReloadDataSources();
}
}

Teď už je potřeba jenom si daný záznam v té cílové třídě převzít a zaregistrovat. Potřebuji k tomu třídu DependencyProperty a její metodu Register()…

DependencyProperty
C#
1
2
3
public static readonly DependencyProperty FormProperty
= DependencyProperty.Register("Record", typeof(MyRecord),
typeof(MyDetailForm));

a pak samotnou property Record…

property Record
C#
1
2
3
4
5
6
7
8
9
10
11
12
public MyRecord Record
{
get
{
return (MyRecord)GetValue(FormProperty);
}
set
{
SetValue(FormProperty, value);
DataContext = value;
}
}

Nakonec už stačí jednotlivým prvkům v okně nastavit Path na příslušné pole daného záznamu…

Path binding
XHTML
1
2
3
4
5
<Label Content="Název">
</Label>
<TextBox Name="MyRecordName"
Text="{Binding Path=Name}">
</TextBox>

A to je v podstatě vše. Po submitu formuláře si pak nadřazené okno převezme property Record z dialogu, který má díky provázanosti na pole aktualizované hodnoty a naloží s ním podle svého – v tomto případě zavolá příkaz Update v obslužném objektu a aktualizuje grid.

Komentování je uzavřeno.