MVVM模式--游戲地圖編輯器開發(fā)隨筆(4)

感覺也是很久沒有寫文章了,今天的問題仍然是與綁定有關(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,一搜就是。

歡迎指正。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容