Atsiprašau už beveik savaitės pertrauką, vis tik gimtadienis reikalauja nemažai jėgų bei sveikatos :)
Abipusis duomenų susiejimas (two-way databinding) yra labai patogi, bet retai naudojama (iš dalies dėl savo ribotumo) ASP.NET galimybė. Jos dėka galima ne tik automatiškai užpildyti komponentus duomenimis iš verslo objekto, bet ir nuskaityti pasikeitusias reikšmes atgal į verslo objektą. Deja, bet abipusis duomenų susiejimas prieinamas tik GridView, FormView ir DetailsView komponentuose. Kadangi šiuo metu aš dirbu prie projekto, kuriame bandau kiek galima daugiau supaprastinti operavimą duomenimis, norėčiau parodyti jums minimalų abipusio duomenų susiejimo panaudojimą FormView pagrindu.
Tarkime, pagal duomenų bazės schemą mes sugeneravome žemiau pateiktus verslo objektus:

Tam, kad duomenis būtų ne tik pakraunamos į komponentus, bet ir nuskaitomos atgal, vietoje įprasto Eval metodo naudojame Bind metodą. Tas pats galioje ir pasirenkant įrašą iš elementų sąrašo:

Dabar prasidės pati įdomiausia dalis. Kaip tikriausiai pastebėjote, mano FormView komponentas naudojasi dataProducts duomenų šaltiniu (Data Source), o išsiskleidžiamas sąrašas ddlCategories – dataCategories. Pasižiūrėkime į jų aprašus:

dataCategories duomenų šaltinis naudoja CategoryController klasės GetList metodą kategorijų sąrašui gauti, kuris mano atveju atrodo taip:

dataProducts duomenų šaltinis naudoja GetProductByID metodą objekto gavimui ir Update metodą duomenų atnaujinimui. Šioje vietoje tikriausiai gali kilti klausimas: o kur Update metodo argumentai? Kadangi aš nurodžiau DataObjectTypeName savybę, ASP.NET sukurs man Product tipo objektą ir užpildys jo savybes pagal nurodytus Bind susiejimus. Naudojamas Update metodas parodytas žemiau:

Kaip matyti, abipusis duomenų susiejimas tikrai yra įdomus ir patogus dalykas. Šiuo metu jis turi pakankamai daug rimtų apribojimų, bet tikėkimės Microsoft darbai judės šia kryptimi. Jeigu jus šiuo metu naudojate kokį nors abipusio susiejimo sprendimą - parašykite! Manau ne tik man bus naudinga sužinoti apie tokių egzistavimą, o kol kas tiek…
Rodyk draugams





2007-11-27 15:36
Naudoju two-way binding automatiniam formų kūrimui. Sukūriau klasę TemplateBuilder: IBindableTemplate, kurios InstantiateIn metodas generuoja formą (textbox,combobox su atitinkamais validatoriais – datos, skaičių, ir pan.), o ExtractValues – gražina visas reikšmes (binding`ui)
Kiekvienai formai turime:
1) xml failas su formos aprašymų (laukų sąrašas, jų tipai, ir pan.) bei resursų failai su pavadinimai (reikia localization`ui)
2) aspx puslapyje: DataSource (mano atveju – naudoju SqlDataSource bei stored procedumano atveju – naudoju SqlDataSource bei stored proceduraūras Sql serveryje) ir tuščias FormView (kuris OnInit event`e sukuria ItemTemplate bei EditItemTemplate = new TemplateBuilder(..) )
Visos programos formos atrodo vienodai, nesunkiai valdomos (pvz. norint pridėti dar vieną laukelį - užtenka įdėti vieną eilutę į xml`ą, o label, textbox/combobox, validatoriai ir kt. smulkmenos sukuriami programiškai)
2007-11-27 16:37
Būtų visai įdomu detaliau pasižiūrėti į šį metodą (mintis tikrai nebloga). Klausimas tik kaip operuojama objektais (kurie kuriami pagal XML failą) serverinėje pusėje (CS faile)?
Redagavo seriog 2007-11-27 16:38
2007-11-27 21:20
Pateikiu esmines kodo dalis:
class TemplateBuilder: IBindableTemplate
public void InstantiateIn(Control container)
{
…
ctrl = new TextBox/DropDownList/CheckBoxList/Label/CheckBox();
ctrl.DataBinding += new EventHandler(ctrl_DataBinding);
ctrl.ID = name; //name - unikalus ID, nuskaitytas is xml`o
…
}
private void ctrl_DataBinding(object sender, EventArgs e)
{
//Getting DataRowView out of sender (TextBox or Label)
WebControl ctrl = (WebControl)sender;
FormView fv = (FormView)ctrl.NamingContainer;
DataRowView drv = (DataRowView)fv.DataItem;
//DataContainer - pagalbinis struct`as (laikomas isparsintas xml node`as)
//dataDict - visu isparsintu node kolekcija
DataContainer data = dataDict[ctrl.ID];
string s = drv[data.DBField].ToString();
if (ctrl.GetType() == typeof(Label)) ((Label)ctrl).Text = s;
else if (ctrl.GetType() == typeof(TextBox)) ((TextBox)ctrl).Text = s;
else if (ctrl.GetType() == typeof(CheckBox)) ((CheckBox)ctrl).Checked = s == "1";
}
public IOrderedDictionary ExtractValues(Control container)
{
OrderedDictionary od = new OrderedDictionary();
AddAllControls(od, container);
return od;
}
private void AddAllControls(OrderedDictionary od, Control container)
{
foreach (Control c in container.Controls)
{
Type type = c.GetType();
if (type == typeof(TextBox)) od.Add(dataDict[c.ID].DBField, ((TextBox))c.Text);
else if (type == typeof(CheckBox)) od.Add(dataDict[cb.ID].DBField, ((CheckBox)c).Checked);
else AddAllControls(od, c);
}
}
}
————–
Jeigu domina daugiau - mano_username_at_gmail_com. Galėsiu ir veikiantį pavyzdį atsiųsti
2007-11-27 22:37
Ačiū už info.
Šiandien teko pasirašyti savo pagalbinę abipusio susiejimo klasę, greitai pateiksiu info apie ją bloge.