感覺也是很久沒有寫文章了,今天的問題仍然是與綁定有關(guān),當(dāng)然不再是簡單的集合數(shù)據(jù)綁定問題,這次還涉及到事件與RelayCommand綁定所相關(guān)的Converter,以及View層級上一些理解。
========================================================
上篇文章末尾的時候講了在List類中綁定ViewModel中的RelayCommand的時候應(yīng)該用到RelativeSource來重定位DataContext從而跳出ItemsSource的方法,然而在接下來的開發(fā)中又遇到相似的問題。上代碼:
<TabControl TabStripPlacement="Top"
DataContext="{Binding Source={StaticResource Locator}, Path=LibraryControl}">
<TabItem Header="怪物庫">
<ListView ItemsSource="{Binding MonsterSection}" x:Name="monster_ListView">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseMove">
<command:EventToCommand Command="{Binding DataContext.MonsterMouseMove,
RelativeSource={RelativeSource AncestorType={x:Type TabControl},
Mode=FindAncestor, AncestorLevel=1}}"
EventArgsConverter="{StaticResource mscv}"
EventArgsConverterParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type TextBlock}, Mode=FindAncestor}}"
PassEventArgsToCommand="True"/>
</i:EventTrigger>
</TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</TabItem>
</TabControl>
為了方便觀看我刪掉了其他多余的代碼,需要注意的是在Command的RelativeSource里面AncestorType是TabControl而不是他的任何一個TabItem,而其實(shí)這里只能是TabControl,雖然的確DataContext是具有繼承特征的(例如一個TabItem的DataContext為空則會往UI樹向上尋找可填充的DataContext),但是這里用TabItem卻沒辦法很好的繼承這個DataContext,那是因?yàn)镈ataTemplate,以及其他模板類的標(biāo)簽,在UI樹的層面上都是和Item平行的,也就是:
<TabControl>
<Template>
<!--sth..-->
</Template>
<TabItem>
<!--sth..-->
</TabItem>
</TabControl>
TabItem并不是這個模板中內(nèi)容的祖先,雖然繼承了同樣的DataContext,卻無法被尋找到,在有模板的情況下直接找具有有效Context的UI層級似乎才是最不容易出錯的方法。而在模板之中就不用顧慮這些,直接用FindAncestor的方法就可以找到,順帶一提就是RelativeSource在FindAncestor的時候是會自動忽略非目標(biāo)類型的層級的(詳見深入淺出WPF的綁定一章)。
=======================================================
在MVVM模式下編寫程序時,常常會遇到事件與RelayCommand的各種復(fù)雜的轉(zhuǎn)換,其中就牽涉到事件的各個參數(shù)的傳遞與轉(zhuǎn)換,其中最為基本的路由事件的參數(shù)轉(zhuǎn)換器:
public class Converter : IEventArgsConverter
{
public object Convert(object value, object parameter) {
//need to return a value;
}
}
其中value是當(dāng)前轉(zhuǎn)換的事件的EventArgs參數(shù),另外一個則是在View中傳入的,Convert是必須實(shí)現(xiàn)的接口,實(shí)現(xiàn)之后就可以被外部引用并使用了。
其實(shí)這個地方的難點(diǎn)主要在于傳入的參數(shù),考慮到后面程序的需要而正確的傳入?yún)?shù)很是考驗(yàn)綁定知識的基本功..
順帶一提在這次開發(fā)中又發(fā)現(xiàn)一個wpf萬年老bug,那就是Mouse.GetPositon(Control)這個函數(shù)無法返回正確的相對坐標(biāo)值,需要利用當(dāng)前的EventArgs來返回正確的坐標(biāo),例如args.GetPosition(Control),詳細(xì)請看StackOverflow,一搜就是。
歡迎指正。