{"id":62,"date":"2011-11-29T21:01:00","date_gmt":"2011-11-29T21:01:00","guid":{"rendered":"http:\/\/tpodolak.com.hostingasp.pl\/blog\/2011\/11\/29\/interactivity-oraz-interaction\/"},"modified":"2016-01-31T00:31:37","modified_gmt":"2016-01-31T00:31:37","slug":"interactivity-oraz-interaction","status":"publish","type":"post","link":"https:\/\/tpodolak.com\/blog\/2011\/11\/29\/interactivity-oraz-interaction\/","title":{"rendered":"Interactivity oraz Interaction"},"content":{"rendered":"<p><span style=\"font-style: italic;\">Interactions <\/span>oraz <span style=\"font-style: italic;\">Interactivity <\/span>s\u0105 to dwie dll-ki, kt\u00f3re poszerzaj\u0105 spos\u00f3b komunikacji pomi\u0119dzy widokiem oraz <span style=\"font-style: italic;\">ViewModelem<\/span>. Wprowadzaj\u0105 one nowy typ <span style=\"font-style: italic;\">EventTrigger\u00f3w<\/span>(w Silverlighcie nie ma trigger\u00f3w, natomiast w WPF-ie event triggery mo\u017cna praktycznie u\u017cywa\u0107 jedynie do animacji) oraz dodatkowo wprowadzaj\u0105 ciekawe sposoby(funkcje) na interakcj\u0119 widoku z ViewModelem. Pierwszym z tych sposob\u00f3w jest u\u017cycie w\u0142a\u015bciwo\u015bci <span style=\"font-style: italic;\">InvokeCommandAction<\/span>.Jak sama nazwa wskazuje mo\u017cna wywo\u0142a\u0107 komend\u0119 z ViewModelu. Jaka jest r\u00f3\u017cnica mi\u0119dzy wywo\u0142aniem komendy poprzez <span style=\"font-style: italic;\">InvokeCommandAction<\/span>, a <span style=\"font-style: italic;\">Command=&#8221;{Binding CommandName}&#8221;<\/span> ? <span style=\"font-style: italic;\">InvokeCommandAction <\/span>ma t\u0105 przewag\u0119 nad normalnm bindowaniem do property Command,\u017ce pozwala wywo\u0142a\u0107 dan\u0105 komend\u0119 w odpowiedzi na zaj\u015bcie jakiego\u015b zdarzenia na widoku. Przyk\u0142adowe u\u017cycie mo\u017ce wygl\u0105da\u0107 nast\u0119puj\u0105co:<\/p>\n<pre lang=\"xml\">\r\n<Button Content=\"Submit\" IsEnabled=\"{Binding CanSubmit}\">\r\n      <i:Interaction.Triggers>\r\n        <i:EventTrigger EventName=\"MouseMove\">\r\n           <i:InvokeCommandAction Command=\"{Binding SubmitCommand}\"\/>\r\n        <\/i:EventTrigger>\r\n      <\/i:Interaction.Triggers>\r\n<\/Button>\r\n<\/pre>\n<p>Powy\u017cszy przyk\u0142ad dzia\u0142a w nast\u0119puj\u0105cy spos\u00f3b. Za ka\u017cdym razem gdy zostanie wywo\u0142ane zdarzenie <span style=\"font-style: italic;\">MouseMove <\/span>na przycisku, odpalona zostanie komenda <span style=\"font-style: italic;\">SubmitCommand<\/span>. Wad\u0105 u\u017cywania <span style=\"font-style: italic;\">InvokeCommandAction <\/span>jest to, \u017ce sami musimy si\u0119 martwi\u0107 o wygaszenie kontrolki w przypadku gdy dana komenda nie mo\u017ce by\u0107 wykonana. Dlatego te\u017c w pierwszej linii mamy bindowanie w\u0142a\u015bciwo\u015bci <span style=\"font-style: italic;\">IsEnabled <\/span> przycisku do w\u0142a\u015bciwo\u015bci CanSubmit z ViewModelu. Alias i: jest aliasen na namespace interactivity z dll-ki<\/p>\n<pre lang=\"xml\">\r\nSystem.Windows.Interactivity.xmlns:i=\"clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity\".\r\n<\/pre>\n<p>Drugim sposobem powiadomiania ViewModelu o jakim\u015b zdarzeniu w widoku jest u\u017cycie <span style=\"font-style: italic;\">InvokeMethodAction<\/span>. Dzi\u0119ki tej w\u0142a\u015bciwo\u015bci mo\u017cemy bezpo\u015brednio z widoku (z XAML-a) wywo\u0142a\u0107 funkcj\u0119 w ViewModelu. Sk\u0142adnia przedstawia si\u0119 w nast\u0119puj\u0105cy spos\u00f3b:<\/p>\n<pre lang=\"xml\">\r\n<Button Content=\"Submit\" IsEnabled=\"{Binding CanSubmit}\">\r\n     <i:Interaction.Triggers>\r\n       <i:EventTrigger EventName=\"Click\">\r\n        <i:CallMethodAction TargetObject=\"{Binding}\"      Method=\"Submit\"\/>\r\n      <\/i:EventTrigger>\r\n     <\/i:Interaction.Triggers>\r\n<\/Button>\r\n<\/pre>\n<p><span style=\"font-style: italic;\">TargetObject <\/span>jest zbindowany do <span style=\"font-style: italic;\">DataContextu<\/span>, to w\u0142a\u015bnie tam b\u0119dzie szukana funkcja Submit. Nale\u017cy pami\u0119ta\u0107, \u017ce w\u0142a\u015bciwo\u015b\u0107 <span style=\"font-style: italic;\">CallMethodAction <\/span>nie wspiera parametr\u00f3w funkcji. Zatem je\u017celi musimy wywo\u0142a\u0107 jak\u0105\u015b funkcj\u0119 z parametrami, nale\u017cy opakowa\u0107 j\u0105 w funkcj\u0119 bezparametrow\u0105, natomiast wszystkie parametry przekaza\u0107 z w\u0142a\u015bciwo\u015bci ViewModelu.<\/p>\n<p>Kolejnym ciekawym featurem <span style=\"font-style: italic;\">Interactivity <\/span>jest klasa <span style=\"font-style: italic;\">Behavior<T><\/span>. Jest niezast\u0105piona je\u017celi potrzebujemy ingerowa\u0107 w dzia\u0142anie widoku po jakim\u015b zdarzeniu. Nie musimy w\u00f3wczas tworzy\u0107 obs\u0142ugi event\u00f3w w code behind. Mo\u017cemy wy\u0142uska\u0107 dan\u0105 funkcjonalno\u015b\u0107 i zamkn\u0105\u0107 j\u0105 w klasie <span style=\"font-style: italic;\">Behavior <\/span>a nast\u0119pnie doczepi\u0107 do wszystkich widok\u00f3w danego typu. Za\u0142\u00f3\u017cmy, \u017ce sterujemy ListBoxem z poziomu ViewModelu (prze\u0142\u0105czamy SelectedItem). Mo\u017cemy zaznaczy\u0107 jaki\u015b Item, co jednak je\u017celi nasza lista jest bardzo d\u0142uga,a zaznaczamy ostatni element. Na widoku element rzeczywi\u015bcie si\u0119 zaznaczy\u0142 jednak lista si\u0119 nie przewin\u0119\u0142a. Przez co ca\u0142y czas wisz\u0105 elementy z pocz\u0105tku i nie wida\u0107 czy kt\u00f3ry\u015b element jest zaznaczony. Dopiero gdy przeskrolujemy r\u0119cznie <span style=\"font-style: italic;\">ListBoxa <\/span>widzimy, \u017ce rzeczywi\u015bcie prawid\u0142owo zareagowa\u0142 na zmian\u0119 property w <span style=\"font-style: italic;\">ViewModelu<\/span>. Jest to idealna sytuacja, aby stworzy\u0107 w\u0142asny <span style=\"font-style: italic;\">Behavior<\/span>, kt\u00f3ry b\u0119dziemy mogli podczepi\u0107 do wszystkich listbox\u00f3w w ka\u017cdym widoku.<\/p>\n<pre lang=\"csharp\">\r\npublic class Behavior<ListBox>\r\n{\r\n\r\nprotected override void OnAttached()\r\n{\r\n AssociatedObject.SelectionChanged += ListBoxSelectionChanged;\r\n}\r\n\r\nprotected override void OnDetaching()\r\n{\r\n  AssociatedObject.SelectionChanged -= ListBoxSelectionChanged;\r\n}\r\n\r\nprivate void ListBoxSelectionChanged(object sender, SelectionChangedEventArgs e)\r\n{\r\n         if (sender is ListBox && ((ListBox)sender).SelectedItem != null)\r\n         {\r\n             var listBox = sender as ListBox;\r\n             listBox.ScrollIntoView(listBox.SelectedItem);\r\n         }\r\n  }\r\n}\r\n<\/pre>\n<p>Metoda <span style=\"font-style: italic;\">OnAttached <\/span>odpala si\u0119 w momencie, gdy behavior jest podpinany do kontrolki. W metodzie tej powinni\u015bmy podpi\u0105\u0107 si\u0119 pod wszystkie eventy, kt\u00f3re s\u0105 dla nas istotne. W momencie, gdy widok jest niszczony wywo\u0142uje si\u0119 metoda <span style=\"font-style: italic;\">OnDetaching<\/span>, w kt\u00f3rej powinni\u015bmy odpi\u0105\u0107 wszystkie metody od event\u00f3w.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Interactions oraz Interactivity s\u0105 to dwie dll-ki, kt\u00f3re poszerzaj\u0105 spos\u00f3b komunikacji pomi\u0119dzy widokiem oraz ViewModelem. Wprowadzaj\u0105 one nowy typ EventTrigger\u00f3w(w Silverlighcie nie ma trigger\u00f3w, natomiast w WPF-ie event triggery mo\u017cna praktycznie u\u017cywa\u0107 jedynie do animacji) oraz dodatkowo wprowadzaj\u0105 ciekawe sposoby(funkcje) na interakcj\u0119 widoku z ViewModelem. Pierwszym z tych sposob\u00f3w jest u\u017cycie w\u0142a\u015bciwo\u015bci InvokeCommandAction.Jak sama nazwa [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[135,132,133,134,44,45],"tags":[259,260,261,262,190,191],"class_list":["post-62","post","type-post","status-publish","format-standard","hentry","category-behavior","category-interaction","category-interactivity","category-prism","category-silverlight","category-wpf","tag-behavior","tag-interaction","tag-interactivity","tag-prism","tag-silverlight","tag-wpf"],"_links":{"self":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts\/62","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/comments?post=62"}],"version-history":[{"count":4,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts\/62\/revisions"}],"predecessor-version":[{"id":565,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts\/62\/revisions\/565"}],"wp:attachment":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/media?parent=62"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/categories?post=62"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/tags?post=62"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}