xaml中DataTemplate的內容綁定ItemSource以外的對象

xaml中DataTemplate的內容綁定ItemSource以外的對象

問題描述

一般來說在DataTemplate中每個Item所顯示的內容都是跟它所綁定ItemSource相關的,但是有時候我們可能需要在每個Item上綁定顯示一些ItemSource中沒有的東西,比如說在一些監控程序中,可能需要用一個ListBox顯示多個監控數據和一些監控數據中沒有的東西,比如軟件版本號什麼的。

xaml中的綁定途徑

xaml中的Binding有3種途徑綁定數據:ElementName屬性,Source屬性,RelativeSource屬性。這裏簡單的說明一下。

  1. ElementName屬性
    用來綁定界面上有設置過x:Name屬性的元素屬性。
     <StackPanel>
         <Label x:Name="lb_Test" Content="Test"/>
         <Button Content="{Binding ElementName=lb_Test,Path=Content}"/>
     </StackPanel>
  1. Source屬性
    用於綁定確定的對象,如資源字典中的靜態資源
<TextBlock Text="{Binding Source={StaticResource myDataSource}, Path=PersonName}"/>
  1. RelativeSource屬性
    用於綁定不確定的對象,如在DataTemplate中綁定ItemSource以外的對象。這裏這個就是我們需要用到的。

實現代碼

該代碼實現在一個ListBox中爲每個Item綁定ItemSource以外的對象。
按照MVVM的模式,先看ItemSource中綁定的數據和ViewModel,ViewModel作爲整個View的數據源。
ListBox中每個Item綁定的數據,包含一個int和一個string

    public class DataModel : INotifyPropertyChanged
    {
        private int m_Num;
        public int Num 
        {
            get 
            {
                return m_Num;
            }
            set
            {
                m_Num = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Content"));
            }
        }
        
        private string m_Content;
        public string Content
        {
            get
            {
                return m_Content;
            }
            set
            {
                m_Content = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Content"));
            }
        }
        
        public event PropertyChangedEventHandler PropertyChanged;
    }

ViewModel作爲整個頁面的DataContext,它包含一個數組(供ListBox綁定)和一個版本字符串。

    public class ViewModel
    {
        public ObservableCollection<DataModel> ModelList { get; set; }
        public string VersionText { get; set; }
        public ViewModel(List<DataModel> data)
        {
            ModelList = new ObservableCollection<DataModel>(data);
            VersionText = "Ver 1.01";
        }
    }

頁面中的ListBox以ViewModel中的ModelList作爲ItemSource,建立DataTemplate

        <ListBox ItemsSource="{Binding Path=ModelList,Mode=TwoWay}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                    	<!--綁定ItemSource中一個Item的Num屬性-->
                        <TextBlock Text="{Binding Content}"/>
                        
                        <!--綁定ItemSource中一個Item的Num屬性-->
                        <TextBlock Text="{Binding Num}"/>
                        
                        <!--綁定ItemSource以外的一個字符串-->
                        <TextBlock Text="{Binding DataContext.VersionText, RelativeSource={RelativeSource AncestorType=local:MainWindow}}"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

成功綁定在這裏插入圖片描述
這裏的XAML最核心的代碼是這一行

<TextBlock Text="{Binding DataContext.VersionText, RelativeSource={RelativeSource AncestorType=local:MainWindow}}"/>

當xaml渲染到這個TextBlock的時候,它綁定的DataContext已經是ModelList中的其中一個DataModel對象,所以它默認只能訪問到DataModel對象中的Num和Content屬性。這行代碼的功能是將這個TextBlock綁定的DataContext切換爲ViewModel裏面的VersionText屬性,此時這個TextBlock必須綁定中父鏈中的祖先,綁定父級(ModelList)的父級(ViewModel)元素.

RelativeSource={RelativeSource AncestorType=local:MainWindow}

這句的意思是,表明該綁定值需要向上查找父級鏈,直到查找到一個類型爲MainWindow的對象爲止,然後綁定它的DataContext.VersionText屬性。

參考
1.xaml中三種綁定模式的綁定方法
2.xaml中Binding的用法
3.How to: Specify the Binding Source

發佈了15 篇原創文章 · 獲贊 2 · 訪問量 8184
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章