Tuesday, June 22, 2010

Wpf, Resources and DataContext

One of the frustrating things in WPF is that objects in the Resources Collection can't see the DataContext from their containing control. It makes sense when you think about it as they are not within the Logical / Visual Tree, which Dependency Properties can inherit down. Whilst it doesn't normally affect me, today I came across a need to have this.

I've just worked on a view where we want to expose a collection in a next-previous way, and expose a 'CurrentItem' property. Whilst we could have done it in our ViewModel, in our scenario we don't want the ViewModels becoming aware of the next / prev, and just to be aware that they are given a list of items, and one of them is selected.

I went down the approach of a control which inherited from FrameworkElement as it had a DataContext then put it in the Resources Collection. Of course this didn't work as as we said at the beginning, stuff in the Resources cannot access the DataContext. BUT back up a minute... there is a control which seems able to do this - the CollectionViewSource. How does it do it? Heh heh, Reflector revealed the internal hack which MS used to somehow ram the inheritence of DP's into this unsuspecting class.

Nasty, but it just so happens we can exploit this for our own purposes. CollectionViewSource wraps a collection which it can obtain by binding to the DataContext, and it is not marked as sealed so we can extend it and add our own behaviour.

What I ended up doing was subclassing CollectionViewSource and adding a NextCommand, PreviousCommand, and SelectedItem dependency property to my subclass. (side note - we use a OneWayToSource binding to reverse the SelectedItem back onto the ViewModel we can bind to a standard .Net property on the ViewModel).

All sounds good, but there was one more issue. The CollectionViewSource is a bit of a liar, in that when you bind to it, you don't actually bind directly to it, but instead to the Collection it exposes. It makes for a nicer syntax in that 99% of times you use it, all you are interested in is that exposed collection. For us though we need to drill into our actual class to get at our subclasses properties. That's where that strange property on Binding, BindsDirectlyToSource comes in. It lets us probe past that outer facade of the class and get into the real object.

Our code is not far off being acceptable now. It looks something like:

<SummaryContentActionView> <!-- the scaffolding view which uses a template to define the layout -->

<SummaryContentActionView.Resources>
<NextPreviousCollection x:Key="col" Items="{Binding Contract.Items}" SelectedItem="{Binding SelectedItem, Mode=OneWayToSource}" />
</SummaryContentActionView.Resources>

<SummaryContentActionView.MainContent> <!-- object DP exposed from the scaffold contol -->
<StackPanel>
<Button Command="{Binding Source={StaticResource col}, Path=NextCommand, BindsDirectlyToSource=True}" />
</StackPanel>
</SummaryContentActionView.MainContent>


</SummaryContentActionView>

22 comments:

正玲正玲 said...

很喜歡你的部落格 留言支持你 祝你人氣長紅~~~......................................................................

李哲維 said...

生存乃是不斷地在內心與靈魂交戰;寫作是坐著審判自己。......................................................................

祥傑祥傑 said...

在莫非定律中有項笨蛋定律:「一個組織中的笨蛋,恆大於等於三分之二。」.................................................................

AlphonseH_Va哲維 said...

成熟,就是有能力適應生活中的模糊。.................................................................

許紀廷 said...

唯有學習不已的老師,才能認真的教,唯有燃燒自己,才能點亮他人的燈............................................................

宥妃宥妃 said...

字是活的,人和環境的觀察是活的,思想是活的。不管怎樣,就是要有一兩樣是活的。否則都是平庸。............................................................

文辰文辰 said...

開心不開心都是一天,祝您能夠笑著面對一切!............................................................

莊雅和莊雅和莊雅和 said...

Never put off till tomorrow what may be done today.......................................................................

楊儀卉 said...

生存乃是不斷地在內心與靈魂交戰;寫作是坐著審判自己。..................................................

鄭雅琦鄭雅琦 said...

道歉是人類一定必要的禮節..................................................

曹季恩曹季恩 said...

幫你推個文~~期待更新!加油啊!............................................................

邱允成邱允成 said...

大肚能容,了卻人間多少事,滿腔歡喜,笑開天下古今愁。..................................................

淑林林松 said...

好文!值得一推~~加油哦!............................................................

亦奈美妮 said...

愛,拆開來是心和受兩個字。用心去接受對方的一切,用心去愛對方的所有。......................................................................

雅明修任 said...

朋友是一面鏡子............................................................

宗王王王王王穎 said...

財富並非永遠的朋友,但朋友卻是永遠的財富。......................................................................

峻胡邦慧v帆 said...

嗯~蠻不錯耶~~我喜歡 ∩ 3∩............................................................

佳張張張張燕張張張張張 said...

你的部落格感覺很棒,nice job!............................................................

立和辛和胡辛和辛偉 said...

好文章就值得回響,如果可以常常看到您的更新,應該是件很幸福的事情~~...............................................................

159fsaf said...

上班很累,摸個魚輕輕鬆鬆的逛部落

8468 said...

讓好心情回味發酵;壞心情留在文字裡隨時間消逝吧!............................................................

tomas adison said...

That is nice information. I love this types of post.
Thanks a lot..
fostering agencies London