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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章