MVVMLight項目的綁定及各種使用場景示例分析
一、綁定:
主要包含元素綁定和非元素綁定兩種。
1、元素綁定:
是綁定的最簡單形式,源對象是WPF的元素,并且源對象的屬性是依賴項屬性。
根據(jù)我們之前的知識 ,依賴項屬性具有內(nèi)置的更改通知支持。所以當(dāng)我們的源對象中改變依賴項屬性的值時,會立即更新目標對象中的綁定屬性。
以上篇的例子來重寫,我們不用額外定義全局公開的屬性來支持數(shù)據(jù)的顯示。
如下:
<StackPanel Orientation="Vertical" HorizontalAlignment="Left" >
<TextBox x:Name="WelcomeText" Width="200" Margin="10,10,0,0"></TextBox>
<TextBlock Text="{Binding ElementName=WelcomeText,Path=Text,StringFormat='Hello \{0\}'}" Margin="10,10,0,0"></TextBlock>
</StackPanel>
TextBlock 綁定了名稱為WelcomeText的元素,并且將Path指向Text屬性,所以他的值會跟著 WelcomeText的變化而變化。
2、非元素類型綁定:
2.1 Source屬性:
綁定具體的數(shù)據(jù)對象:如系統(tǒng)信息跟我們定義的資源數(shù)據(jù)。
定義Window下的全局資源
<Window.Resources>
<SolidColorBrush x:Key="BorderBrush">Red</SolidColorBrush>
</Window.Resources>應(yīng)用到視圖中
<StackPanel Margin="10,50,0,0" Orientation="Vertical" >
<TextBlock Text="{Binding Source={x:Static SystemFonts.IconFontFamily},Path=Source}" ></TextBlock>
<TextBlock Text="{Binding Source={StaticResource BorderBrush}}" Foreground="{Binding Source={StaticResource BorderBrush}}" ></TextBlock>
</StackPanel>結(jié)果:

2.2 RelativeSource 屬性:
設(shè)置該屬性 可以根據(jù)當(dāng)前目標對象的相對關(guān)系指向源目標。比如獲取當(dāng)前對象的父親對象、兄弟對象或者自身的其他屬性等一些數(shù)據(jù)。
<StackPanel Margin="10,50,0,0" Orientation="Vertical" ToolTip="top" >
<StackPanel Orientation="Horizontal" >
<TextBlock Width="150" Text="獲取自身寬度:" ></TextBlock>
<TextBlock Width="200" Text="{Binding Path=Width,RelativeSource={RelativeSource Mode=Self}}" ></TextBlock>
</StackPanel>
<StackPanel Orientation="Horizontal" ToolTip="parent" >
<TextBlock Width="150" Text="查找上一層ToolTip:" ></TextBlock>
<TextBlock Text="{Binding Path=ToolTip,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type StackPanel}}}"></TextBlock>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Width="150" Text="查找上二層ToolTip:" ></TextBlock>
<TextBlock Text="{Binding Path=ToolTip,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type StackPanel},AncestorLevel=2}}"></TextBlock>
</StackPanel>
</StackPan>代碼很容易理解,這邊在創(chuàng)建RelativeSource的時候,mode模式有四種類型:
| Mode成員名稱 | 說明 | |
|---|---|---|
| FindAncestor | 引用數(shù)據(jù)綁定元素的父鏈中的上級。 這可用于綁定到特定類型的上級或其子類。 若要指定 AncestorType 和/或 AncestorLevel,這就是應(yīng)使用的模式。 | |
| PreviousData | 允許在當(dāng)前顯示的數(shù)據(jù)項列表中綁定上一個數(shù)據(jù)項(不是包含數(shù)據(jù)項的控件)。 | |
| Self | 引用正在其上設(shè)置綁定的元素,并允許你將該元素的一個屬性綁定到同一元素的其他屬性上。 | |
| TemplatedParent | 引用應(yīng)用了模板的元素,其中此模板中存在數(shù)據(jù)綁定元素。 這類似于設(shè)置 TemplateBindingExtension,且僅在 Binding 位于模板內(nèi)部時適用。 |
注意:AncestorType 指得是查找的對象類型,AncestorLevel 代表搜索的層級的位置,如果是3,則忽略前兩個發(fā)現(xiàn)的元素。
結(jié)果:

2.3 DataContext 屬性:
如果想將一個對象綁定到一個由多個元素組成的視圖塊或者復(fù)合元素中,用DataContext 會更好開發(fā)和維護。如下
<StackPanel Orientation="Vertical" DataContext="UInfo" >
<StackPanel Orientation="Horizontal" >
<TextBlock Text="名稱:" Width="100" ></TextBlock>
<TextBox Text="{Binding Name}" Width="100" ></TextBox>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="性別:" Width="100" ></TextBlock>
<TextBox Text="{Binding Sex}" Width="100" ></TextBox>
</StackPanel>
</StackPanel>二、綁定的各種使用場景:
數(shù)據(jù)綁定有普通的控件綁定應(yīng)用:比如 下拉框、單選框、復(fù)選框、普通文本框 、日期框等;
復(fù)雜的綁定有數(shù)據(jù)列表綁定,用戶控件信息綁定等,比如 ListBox,DataGrid,UserControl綁定等。
1、下拉框:
View代碼:
<StackPanel Margin="10,20,0,50">
<TextBlock Text="下拉框" FontWeight="Bold" FontSize="12" Margin="0,5,0,5" ></TextBlock>
<DockPanel x:Name="Combbox" >
<StackPanel DockPanel.Dock="Left" Width="240">
<ComboBox Width="200" HorizontalAlignment="Left" ItemsSource="{Binding CombboxList}" SelectedItem="{Binding CombboxItem}" DisplayMemberPath="Text" SelectedValuePath="Key" ></ComboBox>
</StackPanel>
<StackPanel DockPanel.Dock="Right" Width="240" Orientation="Horizontal" DataContext="{Binding CombboxItem}" >
<TextBlock Text="{Binding Key,StringFormat='結(jié)果:\{0\}'}" Margin="0,0,15,0" ></TextBlock>
<TextBlock Text="{Binding Text}"></TextBlock>
</StackPanel>
</DockPanel>
</StackPanel>Model代碼:
public class ComplexInfoModel:ObservableObject
{
private String key;
/// <summary>
/// Key值
/// </summary>
public String Key
{
get { return key; }
set { key = value; RaisePropertyChanged(()=>Key); }
}
private String text;
/// <summary>
/// Text值
/// </summary>
public String Text
{
get { return text; }
set { text = value; RaisePropertyChanged(()=>Text); }
}
}ViewModel代碼:
#region 下拉框相關(guān)
private ComplexInfoModel combboxItem;
/// <summary>
/// 下拉框選中信息
/// </summary>
public ComplexInfoModel CombboxItem
{
get { return combboxItem; }
set { combboxItem = value; RaisePropertyChanged(() => CombboxItem); }
}
private List<ComplexInfoModel> combboxList;
/// <summary>
/// 下拉框列表
/// </summary>
public List<ComplexInfoModel> CombboxList
{
get { return combboxList; }
set { combboxList = value; RaisePropertyChanged(()=>CombboxList); }
}
#endregio說明:CombboxItem是一個全局的屬性,作用在當(dāng)前頁面的數(shù)據(jù)上下文中,結(jié)果顯示的內(nèi)容指向下拉框中的選中值,達到共用一個數(shù)據(jù)的目的。
這邊有四個地方需要注意的:ItemsSource:數(shù)據(jù)源;SelectedItem:選中的項;DisplayMemberPath:綁定時顯示的所屬值;SelectedValuePath :綁定時候key的所屬值。
結(jié)果:

2、單選框
<StackPanel Margin="10,0,0,50">
<TextBlock Text="單選框" FontWeight="Bold" FontSize="12" Margin="0,5,0,5" ></TextBlock>
<DockPanel x:Name="RadioButton" >
<StackPanel DockPanel.Dock="Left" Width="240">
<RadioButton Content="{Binding SingleRadio}" IsChecked="{Binding IsSingleRadioCheck}" HorizontalAlignment="Right" Width="240" >
</RadioButton>
</StackPanel>
<StackPanel DockPanel.Dock="Right" Width="240" Orientation="Horizontal">
<TextBlock Text="{Binding IsSingleRadioCheck,StringFormat='結(jié)果:\{0\}'}" ></TextBlock>
</StackPanel>
</DockPanel>
</StackPanel>說明:注意這邊使用到了兩個屬性: SingleRadio,IsSingleRadioCheck,一個用于顯示單選框內(nèi)容,一個用于表示是否選中
結(jié)果:

3、組合單選框
我們一般會用單選框做組合表示唯一選項,比如性別包含男女,但是只能選擇一個。而更多的場景是包含多個選項,但是只能單選的,這時候就需要做單選框組。
<StackPanel Margin="10,0,0,50">
<TextBlock Text="組合單選框" FontWeight="Bold" FontSize="12" Margin="0,5,0,5"></TextBlock>
<DockPanel x:Name="GroupRadioButton" >
<StackPanel DockPanel.Dock="Left" Width="240">
<ItemsControl ItemsSource="{Binding RadioButtons}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<RadioButton Content="{Binding Content}" IsChecked="{Binding IsCheck}" GroupName="RadioButtons"
Command="{Binding DataContext.RadioCheckCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ItemsControl}}">
</RadioButton>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
<StackPanel DockPanel.Dock="Right" Width="240" Orientation="Horizontal">
<TextBlock Text="{Binding RadioButton.Content,StringFormat='結(jié)果:\{0\}'}" ></TextBlock>
</StackPanel>
</DockPanel>
</StackPanel這邊使用了ItemsControl,可以根據(jù)模板來定義內(nèi)容,我們在模板中放置我們需要用到的內(nèi)容。這邊需要注意的是:GroupName用一樣的,來代表這是一個單選控件組合。
這邊有是三個屬性進行綁定相關(guān):
RadioButtons:單選框列表數(shù)據(jù)(循環(huán)綁定);Content:單選框顯示的內(nèi)容;IsCheck:單選框的是否選中。
結(jié)果:

4、復(fù)選框,復(fù)選框與單選框的使用情況類似:
<StackPanel Margin="10,0,0,50">
<TextBlock Text="復(fù)合框" FontWeight="Bold" FontSize="12" Margin="0,5,0,5" ></TextBlock>
<DockPanel x:Name="GroupCheckButton" >
<StackPanel DockPanel.Dock="Left" Width="240">
<ItemsControl ItemsSource="{Binding CheckButtons}" x:Name="cbt" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Content}" IsChecked="{Binding IsCheck}"
Command="{Binding DataContext.CheckCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ItemsControl}}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
<StackPanel DockPanel.Dock="Right" Width="240" Orientation="Horizontal">
<TextBlock Text="{Binding CheckInfo,StringFormat='結(jié)果:\{0\}'}" ></TextBlock>
</StackPanel>
</DockPanel>
</StackPanel>結(jié)果:

5、樹形控件
View代碼:
<StackPanel Margin="10,0,0,50">
<TextBlock Text="樹" FontWeight="Bold" FontSize="12" Margin="0,5,0,5" ></TextBlock>
<DockPanel x:Name="TreeButton" >
<StackPanel DockPanel.Dock="Left" Width="240">
<TreeView ItemsSource="{Binding TreeInfo}" x:Name="tree" BorderThickness="0">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text="{Binding NodeName}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</StackPanel>
<StackPanel DockPanel.Dock="Right" Width="240" Orientation="Horizontal" DataContext="{Binding SelectedItem,ElementName=tree}">
<TextBlock Text="結(jié)果:"/>
<TextBlock Text="{Binding NodeID,StringFormat='NodeID:\{0\}'}" Margin="0,0,20,0" />
<TextBlock Text="{Binding NodeName,StringFormat='NodeName:\{0\}'}"/>
</StackPanel>
</DockPanel>
</StackPanel>Model代碼
public class TreeNodeModel : ObservableObject
{
public string NodeID { get; set; }
public string NodeName { get; set; }
public List<TreeNodeModel> Children { get; set; }
}ViewModel代碼
#region 樹控件
private List<TreeNodeModel> treeInfo;
/// <summary>
/// 樹控件數(shù)據(jù)信息
/// </summary>
public List<TreeNodeModel> TreeInfo
{
get { return treeInfo; }
set { treeInfo = value; RaisePropertyChanged(()=>TreeInfo); }
}
#endregion結(jié)果:

6、ListBox
當(dāng)我們需要用到循環(huán)的列表內(nèi)容,并且模板化程度高的時候,建議使用ListBox來做綁定。
View代碼:
<StackPanel Margin="10,0,0,50" Orientation="Vertical" >
<TextBlock Text="ListBox模板" FontWeight="Bold" FontSize="12" Margin="0,5,0,5" ></TextBlock>
<DockPanel >
<StackPanel HorizontalAlignment="Left" DockPanel.Dock="Left" >
<ListBox x:Name="lb" ItemsSource="{Binding ListBoxData}" Width="500" BorderThickness="0" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Width="{Binding ActualWidth,RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Image Source="{Binding Img}" Width="96" Height="96"/>
<TextBlock HorizontalAlignment="Center" Text="{Binding Info}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
<StackPanel DockPanel.Dock="Right" DataContext="{Binding SelectedItem,ElementName=lb}" Margin="15" Orientation="Vertical" >
<TextBlock Text="{Binding Info,StringFormat='選中:\{0\}'}" ></TextBlock>
</StackPanel>
</DockPanel>
</StackPanel>ViewModel代碼:
#region ListBox 模板
private IEnumerable listBoxData;
/// <summary>
/// LisBox數(shù)據(jù)模板
/// </summary>
public IEnumerable ListBoxData
{
get { return listBoxData; }
set { listBoxData = value;RaisePropertyChanged(()=>ListBoxData); }
}
#endregion初始數(shù)據(jù):
private void InitListBoxList()
{
ListBoxData = new ObservableCollection<dynamic>(){
new { Img="/MVVMLightDemo;component/Images/1.jpg",Info="櫻桃" },
new { Img="/MVVMLightDemo;component/Images/2.jpg",Info="葡萄" },
new { Img="/MVVMLightDemo;component/Images/3.jpg",Info="蘋果" },
new { Img="/MVVMLightDemo;component/Images/4.jpg",Info="獼猴桃" },
new { Img="/MVVMLightDemo;component/Images/5.jpg",Info="檸檬" },
};
結(jié)果:

7、用戶控件的集合綁定:
ListBox的列表綁定遠遠不能滿足我們實際工作中的需求,
出于對靈活性、復(fù)用性以及代碼精簡的考慮,需要保證循環(huán)列表中的單個元素是獨立的元素片段,類似Web中的局部視圖。 這時候,使用用戶控件會好很多。
我們先寫一個用戶控件,分別設(shè)置了他的樣式和綁定的屬性值,如下:
<UserControl x:Class="MVVMLightDemo.Content.FruitInfoView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Grid.Resources>
<Style TargetType="{x:Type StackPanel}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="RenderTransform">
<Setter.Value>
<RotateTransform Angle="10"></RotateTransform>
</Setter.Value>
</Setter>
<Setter Property="Background" Value="#3B9CFB" />
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<StackPanel Orientation="Vertical" Margin="10">
<Image Source="{Binding Img}" Width="96" Height="96" />
<TextBlock HorizontalAlignment="Center" Text="{Binding Info}"/>
</StackPanel>
</Grid>
</UserControl>在目標視圖頁面注冊并使用:
xmlns:Content="clr-namespace:MVVMLightDemo.Content"
<StackPanel Margin="10,0,0,50" Orientation="Vertical" >
<TextBlock Text="用戶控件模板列表" FontWeight="Bold" FontSize="12" Margin="0,5,0,5" ></TextBlock>
<StackPanel HorizontalAlignment="Left" Width="500" >
<ItemsControl ItemsSource="{Binding FiList}" HorizontalAlignment="Left" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<Content:FruitInfoView />
</DataTemplate>
</ItemsControl.ItemTemplate>
<!-- 面板顯示模板 -->
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal">
</WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</StackPanel>
</StackPanel>結(jié)果:

后記:這篇更確切的說是綁定的相關(guān)知識,只是應(yīng)用了MVVM模式來實現(xiàn)。
工作太忙了,寫的太慢,其實后面幾篇都已經(jīng)成稿了,一直放在Note里面等待認真檢查,品質(zhì)太差怕誤導(dǎo)其他開發(fā)人員。
以上就是MVVMLight項目的綁定及各種使用場景示例分析的詳細內(nèi)容,更多關(guān)于MVVMLight項目的綁定及各種使用場景的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android開發(fā)之imageView圖片按比例縮放的實現(xiàn)方法
這篇文章主要介紹了Android開發(fā)之imageView圖片按比例縮放的實現(xiàn)方法,較為詳細的分析了Android中ImageView控件的scaleType屬性控制圖片縮放的具體用法,需要的朋友可以參考下2016-01-01
Flutter?Widget?之StatefulBuilder構(gòu)建方法詳解
這篇文章主要為大家介紹了Flutter?Widget?之StatefulBuilder構(gòu)建方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-11-11

