利刃 MVVMLight 4:綁定和綁定的各類使用場景

1、綁定:

 主要包含元素綁定和非元素綁定兩種。express

一、元素綁定,是綁定的最簡單形式,源對象是WPF的元素,而且源對象的屬性是依賴項屬性。app

根據咱們以前的知識 ,依賴項屬性具備內置的更改通知支持。因此當咱們的源對象中改變依賴項屬性的值時,會當即更新目標對象中的綁定屬性。ui

以上篇的例子來重寫,咱們不用額外定義全局公開的屬性來支持數據的顯示。this

以下:spa

1  <StackPanel Orientation="Vertical" HorizontalAlignment="Left" >
2         <TextBox x:Name="WelcomeText" Width="200" Margin="10,10,0,0"></TextBox>
3         <TextBlock Text="{Binding ElementName=WelcomeText,Path=Text,StringFormat='Hello \{0\}'}" Margin="10,10,0,0"></TextBlock>
4  </StackPanel>

 

 TextBlock 綁定了名稱爲WelcomeText的元素,而且將Path指向Text屬性,因此他的值會跟着 WelcomeText的變化而變化。3d

 

二、非元素類型綁定: code

2.1 Source屬性:綁定具體的數據對象:如系統信息跟咱們定義的資源數據。component

定義Window下的全局資源orm

1     <Window.Resources>
2         <SolidColorBrush x:Key="BorderBrush">Red</SolidColorBrush>
3     </Window.Resources>

應用到視圖中xml

1   <StackPanel Margin="10,50,0,0" Orientation="Vertical" >
2                 <TextBlock Text="{Binding Source={x:Static SystemFonts.IconFontFamily},Path=Source}" ></TextBlock>
3                 <TextBlock Text="{Binding Source={StaticResource BorderBrush}}" Foreground="{Binding Source={StaticResource BorderBrush}}"  ></TextBlock>
4   </StackPanel>

結果:

 

 2.2 RelativeSource 屬性:設置該屬性 能夠根據當前目標對象的相對關係指向源目標。好比獲取當前對象的父親對象、兄弟對象或者自身的其餘屬性等一些數據。

 1            <StackPanel Margin="10,50,0,0" Orientation="Vertical" ToolTip="top" >
 2                 
 3                 <StackPanel Orientation="Horizontal" >
 4                     <TextBlock Width="150" Text="獲取自身寬度:"  ></TextBlock>
 5                     <TextBlock Width="200" Text="{Binding Path=Width,RelativeSource={RelativeSource Mode=Self}}" ></TextBlock>
 6                 </StackPanel>
 7                 
 8                 
 9                 <StackPanel Orientation="Horizontal" ToolTip="parent" >
10                     <TextBlock Width="150" Text="查找上一層ToolTip:" ></TextBlock>  
11                     <TextBlock Text="{Binding Path=ToolTip,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type StackPanel}}}"></TextBlock>
12                 </StackPanel>
13                 
14                                 
15                 <StackPanel Orientation="Horizontal">
16                     <TextBlock Width="150" Text="查找上二層ToolTip:" ></TextBlock>
17                     <TextBlock Text="{Binding Path=ToolTip,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type StackPanel},AncestorLevel=2}}"></TextBlock>
18                 </StackPanel>                               
19 
20             </StackPanel>

 代碼很容易理解,這邊在建立RelativeSource的時候,mode模式有四種類型:

 
  Mode成員名稱 說明
  FindAncestor

引用數據綁定元素的父鏈中的上級。 這可用於綁定到特定類型的上級或其子類。 若要指定 AncestorType 和/或 AncestorLevel,這就是應使用的模式。

  PreviousData

容許在當前顯示的數據項列表中綁定上一個數據項(不是包含數據項的控件)。

  Self

引用正在其上設置綁定的元素,並容許你將該元素的一個屬性綁定到同一元素的其餘屬性上。

  TemplatedParent

引用應用了模板的元素,其中此模板中存在數據綁定元素。 這相似於設置 TemplateBindingExtension,且僅在 Binding 位於模板內部時適用。

 

 

 

 

 

 

 

注意:AncestorType 指得是查找的對象類型,AncestorLevel 表明搜索的層級的位置,若是是3,則忽略前兩個發現的元素。

結果:

2.3 DataContext 屬性:若是想將一個對象綁定到一個由多個元素組成的視圖塊或者複合元素中,用
DataContext 會更好開發和維護。以下
 1             <StackPanel Orientation="Vertical" DataContext="UInfo" >
 2                 
 3                 <StackPanel Orientation="Horizontal" >
 4                     <TextBlock Text="名稱:" Width="100" ></TextBlock>
 5                     <TextBox Text="{Binding Name}" Width="100" ></TextBox>
 6                 </StackPanel>
 7 
 8                 <StackPanel Orientation="Horizontal">
 9                     <TextBlock Text="性別:" Width="100" ></TextBlock>
10                     <TextBox Text="{Binding Sex}" Width="100" ></TextBox>
11                 </StackPanel>
12 
13             </StackPanel>
 

 

2、綁定的各類使用場景:

數據綁定有普通的控件綁定應用:好比 下拉框、單選框、複選框、普通文本框 、日期框等;
複雜的綁定有數據列表綁定,用戶控件信息綁定等,好比 ListBox,DataGrid,UserControl綁定等。

一、下拉框:

View代碼:

 1                 <StackPanel Margin="10,20,0,50">
 2                 <TextBlock Text="下拉框" FontWeight="Bold" FontSize="12" Margin="0,5,0,5" ></TextBlock>
 3                 <DockPanel x:Name="Combbox" >                
 4                     <StackPanel DockPanel.Dock="Left" Width="240">
 5                         <ComboBox Width="200" HorizontalAlignment="Left" ItemsSource="{Binding CombboxList}" SelectedItem="{Binding CombboxItem}" DisplayMemberPath="Text" SelectedValuePath="Key" ></ComboBox>
 6                     </StackPanel>
 7                     
 8                     <StackPanel DockPanel.Dock="Right" Width="240" Orientation="Horizontal" DataContext="{Binding CombboxItem}" >
 9                         <TextBlock Text="{Binding Key,StringFormat='結果:\{0\}'}" Margin="0,0,15,0" ></TextBlock>
10                         <TextBlock Text="{Binding Text}"></TextBlock>
11                     </StackPanel>
12                     
13                     </DockPanel>
14             </StackPanel>

 Model代碼:

 1   public class ComplexInfoModel:ObservableObject
 2     {
 3         private String key;
 4         /// <summary>
 5         /// Key值
 6         /// </summary>
 7         public String Key
 8         {
 9             get { return key; }
10             set { key = value; RaisePropertyChanged(()=>Key); }
11         }
12 
13         private String text;
14         /// <summary>
15         /// Text值
16         /// </summary>
17         public String Text
18         {
19             get { return text; }
20             set { text = value; RaisePropertyChanged(()=>Text); }
21         }
22     }

 ViewModel代碼:

 1         #region 下拉框相關
 2         private ComplexInfoModel combboxItem;
 3         /// <summary>
 4         /// 下拉框選中信息
 5         /// </summary>
 6         public ComplexInfoModel CombboxItem
 7         {
 8             get { return combboxItem; }
 9             set { combboxItem = value; RaisePropertyChanged(() => CombboxItem); }
10         }
11 
12 
13         private List<ComplexInfoModel> combboxList;
14         /// <summary>
15         /// 下拉框列表
16         /// </summary>
17         public List<ComplexInfoModel> CombboxList
18         {
19             get { return combboxList; }
20             set { combboxList = value; RaisePropertyChanged(()=>CombboxList); }
21         }
22         #endregion

說明:CombboxItem是一個全局的屬性,做用在當前頁面的數據上下文中,結果顯示的內容指向下拉框中的選中值,達到共用一個數據的目的。 

這邊有四個地方須要注意的:ItemsSource:數據源;SelectedItem:選中的項;DisplayMemberPath:綁定時顯示的所屬值;SelectedValuePath :綁定時候key的所屬值。 

結果:

  

二、單選框

 1             <StackPanel Margin="10,0,0,50">
 2                 <TextBlock Text="單選框" FontWeight="Bold" FontSize="12" Margin="0,5,0,5" ></TextBlock>
 3                 <DockPanel x:Name="RadioButton" >
 4                     <StackPanel DockPanel.Dock="Left" Width="240">
 5                         <RadioButton Content="{Binding SingleRadio}" IsChecked="{Binding IsSingleRadioCheck}" HorizontalAlignment="Right" Width="240" >
 6                         </RadioButton>
 7                     </StackPanel>
 8                     <StackPanel DockPanel.Dock="Right" Width="240" Orientation="Horizontal">
 9                         <TextBlock Text="{Binding IsSingleRadioCheck,StringFormat='結果:\{0\}'}" ></TextBlock>
10                     </StackPanel>
11                 </DockPanel>
12             </StackPanel>

說明:注意這邊使用到了兩個屬性: SingleRadio,IsSingleRadioCheck,一個用於顯示單選框內容,一個用於表示是否選中

結果:

 

三、組合單選框

咱們通常會用單選框作組合表示惟一選項,好比性別包含男女,可是隻能選擇一個。而更多的場景是包含多個選項,可是隻能單選的,這時候就須要作單選框組。
 1             <StackPanel Margin="10,0,0,50">
 2                 <TextBlock Text="組合單選框" FontWeight="Bold" FontSize="12" Margin="0,5,0,5"></TextBlock>
 3                 <DockPanel x:Name="GroupRadioButton" >
 4                     <StackPanel DockPanel.Dock="Left" Width="240">
 5                         <ItemsControl ItemsSource="{Binding RadioButtons}">
 6                             <ItemsControl.ItemTemplate>
 7                                 <DataTemplate>
 8                                     <RadioButton Content="{Binding Content}" IsChecked="{Binding IsCheck}" GroupName="RadioButtons"
 9                                                  Command="{Binding DataContext.RadioCheckCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ItemsControl}}">  
10                                     </RadioButton>                                    
11                                 </DataTemplate>
12                             </ItemsControl.ItemTemplate>
13                         </ItemsControl>
14                     </StackPanel>
15 
16                     <StackPanel DockPanel.Dock="Right" Width="240" Orientation="Horizontal">
17                         <TextBlock Text="{Binding RadioButton.Content,StringFormat='結果:\{0\}'}" ></TextBlock>
18                     </StackPanel>
19                 </DockPanel>
20             </StackPanel>

這邊使用了ItemsControl,能夠根據模板來定義內容,咱們在模板中放置咱們須要用到的內容。這邊須要注意的是:GroupName用同樣的,來表明這是一個單選控件組合。

這邊有是三個屬性進行綁定相關:
RadioButtons:單選框列表數據(循環綁定);Content:單選框顯示的內容;IsCheck:單選框的是否選中。  

結果:

 

四、複選框,複選框與單選框的使用狀況相似:

 1   <StackPanel Margin="10,0,0,50">
 2                 <TextBlock Text="複合框" FontWeight="Bold" FontSize="12" Margin="0,5,0,5" ></TextBlock>
 3                 <DockPanel x:Name="GroupCheckButton" >
 4                     <StackPanel DockPanel.Dock="Left" Width="240">
 5                         <ItemsControl ItemsSource="{Binding CheckButtons}" x:Name="cbt" >
 6                             <ItemsControl.ItemTemplate>
 7                                 <DataTemplate>
 8                                     <CheckBox Content="{Binding Content}" IsChecked="{Binding IsCheck}"
 9                                                  Command="{Binding DataContext.CheckCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ItemsControl}}"/>
10                                 </DataTemplate>
11                             </ItemsControl.ItemTemplate>
12                         </ItemsControl>
13                     </StackPanel>
14 
15                     <StackPanel DockPanel.Dock="Right" Width="240" Orientation="Horizontal">
16                         <TextBlock Text="{Binding CheckInfo,StringFormat='結果:\{0\}'}" ></TextBlock>
17                     </StackPanel>
18                 </DockPanel>
19   </StackPanel>            

 結果:

 

五、樹形控件

View代碼:

 1   <StackPanel Margin="10,0,0,50">
 2                 <TextBlock Text="" FontWeight="Bold" FontSize="12" Margin="0,5,0,5" ></TextBlock>
 3                 <DockPanel x:Name="TreeButton" >
 4                     <StackPanel DockPanel.Dock="Left" Width="240">
 5                             <TreeView ItemsSource="{Binding TreeInfo}" x:Name="tree" BorderThickness="0">
 6                             <TreeView.ItemTemplate>
 7                                 <HierarchicalDataTemplate ItemsSource="{Binding Children}">
 8                                     <TextBlock Text="{Binding NodeName}"/>
 9                                 </HierarchicalDataTemplate>
10                             </TreeView.ItemTemplate>
11                         </TreeView>
12                     </StackPanel>
13                     
14                     <StackPanel DockPanel.Dock="Right" Width="240" Orientation="Horizontal" DataContext="{Binding SelectedItem,ElementName=tree}">
15                             <TextBlock Text="結果:"/>
16                         <TextBlock Text="{Binding NodeID,StringFormat='NodeID:\{0\}'}"  Margin="0,0,20,0"  />
17                         <TextBlock Text="{Binding NodeName,StringFormat='NodeName:\{0\}'}"/>
18                     </StackPanel>                    
19                 </DockPanel>
20  </StackPanel>

Model代碼

1  public class TreeNodeModel : ObservableObject
2     {
3         public string NodeID { get; set; }
4         public string NodeName { get; set; }
5         public List<TreeNodeModel> Children { get; set; }
6     }

ViewModel代碼

 1   #region 樹控件
 2 
 3         private List<TreeNodeModel> treeInfo;
 4         /// <summary>
 5         /// 樹控件數據信息
 6         /// </summary>
 7         public List<TreeNodeModel> TreeInfo
 8         {
 9             get { return treeInfo; }
10             set { treeInfo = value; RaisePropertyChanged(()=>TreeInfo); }
11         }
12 
13 
14   #endregion

 結果:

 

六、ListBox

當咱們須要用到循環的列表內容,而且模板化程度高的時候,建議使用ListBox來作綁定。
View代碼:
 1             <StackPanel Margin="10,0,0,50" Orientation="Vertical" >
 2                 <TextBlock Text="ListBox模板" FontWeight="Bold" FontSize="12" Margin="0,5,0,5" ></TextBlock>
 3                     <DockPanel >
 4                         <StackPanel HorizontalAlignment="Left" DockPanel.Dock="Left" >
 5                             <ListBox x:Name="lb" ItemsSource="{Binding ListBoxData}" Width="500" BorderThickness="0" >
 6                                 <ListBox.ItemsPanel>
 7                                     <ItemsPanelTemplate>
 8                                         <WrapPanel Width="{Binding ActualWidth,RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"/>
 9                                     </ItemsPanelTemplate>
10                                 </ListBox.ItemsPanel>
11 
12                                 <ListBox.ItemTemplate>
13                                     <DataTemplate>
14                                         <StackPanel>
15                                             <Image Source="{Binding Img}" Width="96" Height="96"/>
16                                             <TextBlock HorizontalAlignment="Center" Text="{Binding Info}"/>
17                                         </StackPanel>
18                                     </DataTemplate>
19                                 </ListBox.ItemTemplate>
20                             </ListBox>
21                         </StackPanel>
22 
23                         <StackPanel DockPanel.Dock="Right" DataContext="{Binding SelectedItem,ElementName=lb}" Margin="15" Orientation="Vertical" >
24                             <TextBlock Text="{Binding Info,StringFormat='選中:\{0\}'}" ></TextBlock>
25                         </StackPanel>
26                     </DockPanel>
27                 </StackPanel>

ViewModel代碼:

 1         #region ListBox 模板
 2 
 3         private IEnumerable listBoxData;
 4         /// <summary>
 5         /// LisBox數據模板
 6         /// </summary>
 7         public IEnumerable ListBoxData
 8         {
 9             get { return listBoxData; }
10             set { listBoxData = value;RaisePropertyChanged(()=>ListBoxData); }
11         }
12 
13         #endregion

初始數據:

 1    private void InitListBoxList()
 2         {
 3             ListBoxData = new ObservableCollection<dynamic>(){
 4               new { Img="/MVVMLightDemo;component/Images/1.jpg",Info="櫻桃" },
 5               new { Img="/MVVMLightDemo;component/Images/2.jpg",Info="葡萄" },
 6               new { Img="/MVVMLightDemo;component/Images/3.jpg",Info="蘋果" },
 7               new { Img="/MVVMLightDemo;component/Images/4.jpg",Info="獼猴桃" },
 8               new { Img="/MVVMLightDemo;component/Images/5.jpg",Info="檸檬" },
 9            };
10         }

 結果:

 

 

 

七、用戶控件的集合綁定:

ListBox的列表綁定遠遠不能知足咱們實際工做中的需求,
出於對靈活性、複用性以及代碼精簡的考慮,須要保證循環列表中的單個元素是獨立的元素片斷,相似Web中的局部視圖。 這時候,使用用戶控件會好不少。
 
咱們先寫一個用戶控件,分別設置了他的樣式和綁定的屬性值,以下:
 1 <UserControl x:Class="MVVMLightDemo.Content.FruitInfoView"
 2              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
 5              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
 6              mc:Ignorable="d" 
 7              d:DesignHeight="300" d:DesignWidth="300">
 8     <Grid>
 9         <Grid.Resources>
10             <Style TargetType="{x:Type StackPanel}">
11                 <Style.Triggers>
12                     <Trigger Property="IsMouseOver" Value="True">
13                         <Setter Property="RenderTransform">
14                             <Setter.Value>
15                                 <RotateTransform Angle="10"></RotateTransform>
16                             </Setter.Value>
17                         </Setter>
18                         <Setter Property="Background" Value="#3B9CFB" />
19                     </Trigger>
20                 </Style.Triggers>
21 </Style>
22         </Grid.Resources>
23         
24         
25         <StackPanel Orientation="Vertical" Margin="10">
26             <Image Source="{Binding Img}" Width="96" Height="96" />
27             <TextBlock HorizontalAlignment="Center" Text="{Binding Info}"/>
28         </StackPanel>
29         
30     </Grid>
31 </UserControl>

 在目標視圖頁面註冊並使用:

1 xmlns:Content="clr-namespace:MVVMLightDemo.Content" 
 1  <StackPanel Margin="10,0,0,50" Orientation="Vertical" >
 2                     <TextBlock Text="用戶控件模板列表" FontWeight="Bold" FontSize="12" Margin="0,5,0,5" ></TextBlock>
 3                     <StackPanel HorizontalAlignment="Left" Width="500" >
 4                          <ItemsControl ItemsSource="{Binding FiList}" HorizontalAlignment="Left" >
 5                             <ItemsControl.ItemTemplate>
 6                                 <DataTemplate>
 7                                     <Content:FruitInfoView />
 8                                 </DataTemplate>                       
 9                             </ItemsControl.ItemTemplate>
10                              
11                             <!-- 面板顯示模板 -->
12                             <ItemsControl.ItemsPanel>
13                                 <ItemsPanelTemplate>
14                                     <WrapPanel Orientation="Horizontal">
15                                     </WrapPanel>
16                                 </ItemsPanelTemplate>
17                             </ItemsControl.ItemsPanel>
18                              
19                         </ItemsControl>
20                         
21                     </StackPanel>
22  </StackPanel>

  結果:

 

後記:這篇更確切的說是綁定的相關知識,只是應用了MVVM模式來實現。

工做太忙了,寫的太慢,其實後面幾篇都已經成稿了,一直放在Note裏面等待認真檢查,品質太差怕誤導其餘開發人員。

 

點擊下載代碼

 

轉載請標明出處,謝謝
相關文章
相關標籤/搜索