DataTemplate Binding to Interface

在WPF内可以使用DataTemplate,来辅助完成对对象集合做DataBinding的工作。并且透过DataTemplate的DataType属性,来让对象集合中不同的对象,经过DataBinding之后能有「不同的外观」。简单的范例如下:不同的车辆类型,会依照车辆类型,呈现不同的详细数据。

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
namespace BindingInterfaceSample
{
     public class Car
     {
         public string Name { get ; set ; }
     }
 
     public class Truck : Car
     {
         public int MaxLoad { get ; set ; }
     }
 
     public class Roadster : Car
     {
         public int MaxSpeed { get ; set ; }
     }
}

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
< Window x:Class = "BindingInterfaceSample.MainWindow"
         xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:clk = "clr-namespace:BindingInterfaceSample"
         Title = "MainWindow" Height = "350" Width = "525" >
     < ItemsControl >
         < ItemsControl.Items >
             < clk:Truck Name = "Truck01" MaxLoad = "100" />
             < clk:Truck Name = "Truck02" MaxLoad = "500" />
             < clk:Roadster Name = "Roadster01" MaxSpeed = "99" />
         </ ItemsControl.Items >
         < ItemsControl.Resources >
             < DataTemplate DataType = "{x:Type clk:Truck}" >
                 < WrapPanel >
                     < TextBlock Text = "Truck" />
                     < TextBlock Text = "{Binding Path=MaxLoad}" />
                 </ WrapPanel >
             </ DataTemplate >
             < DataTemplate DataType = "{x:Type clk:Roadster}" >
                 < WrapPanel >
                     < TextBlock Text = "Roadster" />
                     < TextBlock Text = "{Binding Path=MaxSpeed}" />
                 </ WrapPanel >
             </ DataTemplate >
         </ ItemsControl.Resources >
     </ ItemsControl >
</ Window >

 

 

反过来说,也可以经由DataTemplate的DataType属性,来让对象集合中不同的对象,经过DataBinding之后能有「相同的外观」。简单的范例如下:只要是车,都只呈现车的数据。

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
namespace BindingInterfaceSample
{
     public class Car
     {
         public string Name { get ; set ; }
     }
 
     public class Truck : Car
     {
         public int MaxLoad { get ; set ; }
     }
 
     public class Roadster : Car
     {
         public int MaxSpeed { get ; set ; }
     }
}

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
< Window x:Class = "BindingInterfaceSample.MainWindow"
         xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:clk = "clr-namespace:BindingInterfaceSample"
         Title = "MainWindow" Height = "350" Width = "525" >
     < ItemsControl >
         < ItemsControl.Items >
             < clk:Truck Name = "Truck01" MaxLoad = "100" />
             < clk:Truck Name = "Truck02" MaxLoad = "500" />
             < clk:Roadster Name = "Roadster01" MaxSpeed = "99" />
         </ ItemsControl.Items >
         < ItemsControl.Resources >
             < DataTemplate DataType = "{x:Type clk:Car}" >
                 < Button Content = "{Binding Path=Name}" />
             </ DataTemplate >
         </ ItemsControl.Resources >
     </ ItemsControl >
</ Window >

 

 

而在让对象集合中不同的对象,经过DataBinding之后能有「相同的外观」。这个使用情景中,DataTemplate的DataType如果设定为Interface型别,在WPF中会出现意外的执行结果。简单的范例如下:DataType设定为Interface型别,会无法对应DataTemplate。

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
namespace BindingInterfaceSample
{
     public interface ICar
     {
         string Name { get ; set ; }
     }
 
     public class Truck : ICar
     {
         public string Name { get ; set ; }
 
         public int MaxLoad { get ; set ; }       
     }
 
     public class Roadster : ICar
     {
         public string Name { get ; set ; }
 
         public int MaxSpeed { get ; set ; }
     }
}

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
< Window x:Class = "BindingInterfaceSample.MainWindow"
         xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:clk = "clr-namespace:BindingInterfaceSample"
         Title = "MainWindow" Height = "350" Width = "525" >
     < ItemsControl >
         < ItemsControl.Items >
             < clk:Truck Name = "Truck01" MaxLoad = "100" />
             < clk:Truck Name = "Truck02" MaxLoad = "500" />
             < clk:Roadster Name = "Roadster01" MaxSpeed = "99" />
         </ ItemsControl.Items >
         < ItemsControl.Resources >
             < DataTemplate DataType = "{x:Type clk:ICar}" >
                 < Button Content = "{Binding Path=Name}" />
             </ DataTemplate >
         </ ItemsControl.Resources >
     </ ItemsControl >
</ Window >

 

 

遇到必须设定DataTemplate的DataType为Interface型别的情景。解决的方法很简单:只要改写数据系结容器使用的DataTemplateSelector,增加以Interface型别做索引,查询Resource里的DataTemplate,再用这个DataTemplate来做DataBinding。简单的范例如下:只要是有实做车接口,都只呈现车的数据。

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
namespace BindingInterfaceSample
{
     public interface ICar
     {
         string Name { get ; set ; }
     }
 
     public class Truck : ICar
     {
         public string Name { get ; set ; }
 
         public int MaxLoad { get ; set ; }
     }
 
     public class Roadster : ICar
     {
         public string Name { get ; set ; }
 
         public int MaxSpeed { get ; set ; }
     }
}

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
< Window x:Class = "BindingInterfaceSample.MainWindow"
         xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:clk = "clr-namespace:BindingInterfaceSample"
         Title = "MainWindow" Height = "350" Width = "525" >
     < ItemsControl >
         < ItemsControl.Items >
             < clk:Truck Name = "Truck01" MaxLoad = "100" />
             < clk:Truck Name = "Truck02" MaxLoad = "500" />
             < clk:Roadster Name = "Roadster01" MaxSpeed = "99" />
         </ ItemsControl.Items >       
         < ItemsControl.Resources >
             < DataTemplate DataType = "{x:Type clk:ICar}" >
                 < Button Content = "{Binding Path=Name}" />
             </ DataTemplate >
         </ ItemsControl.Resources >
         < ItemsControl.ItemTemplateSelector >
             < clk:StandardDataTemplateSelector />
         </ ItemsControl.ItemTemplateSelector >
     </ ItemsControl >
</ Window >

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
namespace BindingInterfaceSample
{
     public class StandardDataTemplateSelector : DataTemplateSelector
     {
         // Methods
         public override DataTemplate SelectTemplate( object item, DependencyObject container)
         {
             #region Require
 
             if (item == null ) throw new ArgumentNullException();
             if (container == null ) throw new ArgumentNullException();
 
             #endregion
 
             // Result
             DataTemplate itemDataTemplate = null ;
 
             // Base DataTemplate
             itemDataTemplate = base .SelectTemplate(item, container);
             if (itemDataTemplate != null ) return itemDataTemplate;
 
             // Interface DataTemplate
             FrameworkElement itemContainer = container as FrameworkElement;
             if (itemContainer == null ) return null ;
 
             foreach (Type itemInterface in item.GetType().GetInterfaces())
             {
                 itemDataTemplate = itemContainer.TryFindResource( new DataTemplateKey(itemInterface)) as DataTemplate;
                 if (itemDataTemplate != null ) break ;
             }
 
             // Return
             return itemDataTemplate;
         }
     }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值