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…
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.
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()…
1 2 3 |
public static readonly DependencyProperty FormProperty
= DependencyProperty.Register("Record", typeof(MyRecord),
typeof(MyDetailForm)); |
a pak samotnou property Record…
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…
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.