Pewnie starzy wyjadacze Windows Phone’owi problem znają, a nawet zapomnieli, że istnieje, ale mi się od czasu do czasu odbija czkawką, gdy próbuję zbudować nową aplikację. Chodzi mianowicie o następującą sytuację.
Budujemy aplikację, mamy w niej stronę, a na stronie kontrolkę z bindingiem. Niech będzie to TextBox.
<TextBox Text="{Binding MyText, Mode=TwoWay}" />
Jak widać nasz TextBox jest związany z polem MyText. Oznacza to, że jeśli w kontrolce wpiszemy jakąś wartość tekstowa powinna ona wylądować w polu MyText.
Nasza aplikacja może wyglądać np. tak:
Dodam, że pod przycisk w AppBar podpięte jest jakieś zachowanie, które wykorzystuje wartość wpisywaną do pola tekstowego. A jednak gdy wpiszę coś do kontrolki i spróbuję użyć tej wartości w metodzie, to widzę, że MyText jest nullem. Czyli pole się nie zaktualizowało.
Po długich rozkminach i czytaniu internetów, w końcu doszłam do wniosku, że nie jest to moja wina. Chodzi mianowicie o to, że bindingi się nie aktualizują, jeśli wciąż na kontrolce jest focus. Co więcej, kod zadziała jeśli najpierw wpiszę tekst, potem tapnę gdzieś poza pole tekstowe (aby stracił focus), to nagle property jest wypełnione.
Rozwiązanie jest proste, trzeba podpiąć zdarzenie Click pod AppBarButton, by znalazł naszą kontrolkę (w tym wypadku TextBox), zaktualizował binding i ustawił focus na stronie głównej:
private void ApplicationBarIconButton_OnClick(object sender, EventArgs e) { var focusedElement = FocusManager.GetFocusedElement() as TextBox; if (focusedElement != null) { var binding = focusedElement.GetBindingExpression(TextBox.TextProperty); if (null != binding) binding.UpdateSource(); } Focus(); // do something with MyText value }
Tylko ja się po raz kolejny na tej platformie pytam… why? Dlaczego muszę to robić sama…? I to dla każdej kontrolki, dla każdego AppBar… Dlaczego to nie jest coś out of the box?
Kwestia wydajności.
Bindingi są wolne dlatego jakby wszystkie domyślne textbox bindował w trybie PropertyChanged to by pewnie zabiło te biedne telefony. Do niedawna nawet w WPFie to był problem, ale potem dodali właściwość UpdateSourceTrigger=PropertyChanged i można było zmienić domyślne zachowanie. Rozumiem, że w WP jeszcze tego nie ma. Jeśli już robić trzeba robić takie numery jak wołanie UpdateSource jawnego to lepiej zaszyć to w jakiś Behavior. Jest kilka rozwiązań w tym guście dostępnych na SO.
Paweł
Dzięki za hint z behavior 🙂 pytanie ‘why?’ było bardziej retoryczne, ale rowniez dziekuje za wyjasnienie