程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> WPF學習筆記 - 10. Binding (3)

WPF學習筆記 - 10. Binding (3)

編輯:關於.NET

6. 數據模板數據模板為展示數據提供了極大的靈活性,我們繼續以前面的例子來看看它的能力。

<Window x:Class="Learn.WPF.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:my="clr-namespace:Learn.WPF"
  Title="Window1">
  <Window.Resources>
    <my:PersonalList x:Key="personals" >
      <my:Personal Name="Tom" Age="10" Sex="Male" />
      <my:Personal Name="Mary" Age="15" Sex="Female" />
      <my:Personal Name="Jack" Age="12" Sex="Male" />
    </my:PersonalList>
  </Window.Resources>
  <Grid>
    <StackPanel DataContext="{StaticResource personals}">
      <ListBox x:Name="listbox1" ItemsSource="{Binding}">
        <ListBox.ItemTemplate>
          <DataTemplate>
            <StackPanel Orientation="Horizontal">
              <TextBlock Text="{Binding Path=Name}" />
              <TextBlock>, </TextBlock>
              <TextBlock Text="{Binding Path=Age}" />
              <TextBlock>,</TextBlock>
              <TextBlock Text="{Binding Path=Sex}" />
            </StackPanel>
          </DataTemplate>
        </ListBox.ItemTemplate>
      </ListBox>
    </StackPanel>
  </Grid>
</Window>

很顯然,利用 ListBox.ItemTemplate.DataTemplate 我們可以用更復雜和更豐富的手段顯示數據源對象,不再僅僅是通過 Path 顯示某單個屬性。不過通常情況下,我們會像 HTML/CSS 那樣將數據模板定義到資源中,以便在多個地方重復使用。

<Window x:Class="Learn.WPF.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:my="clr-namespace:Learn.WPF"
  Title="Window1">
  <Window.Resources>
    <my:PersonalList x:Key="personals" >
      <my:Personal Name="Tom" Age="10" Sex="Male" />
      <my:Personal Name="Mary" Age="15" Sex="Female" />
      <my:Personal Name="Jack" Age="12" Sex="Male" />
    </my:PersonalList>

    <DataTemplate x:Key="myData">
      <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Path=Name}" />
        <TextBlock>,</TextBlock>
        <TextBlock Text="{Binding Path=Age}" />
        <TextBlock>,</TextBlock>
        <TextBlock Text="{Binding Path=Sex}" />
      </StackPanel>
    </DataTemplate>
  </Window.Resources>
  <Grid>
    <StackPanel DataContext="{StaticResource personals}">
      <ListBox x:Name="listbox1" ItemsSource="{Binding}" 
        ItemTemplate="{StaticResource myData}">
      </ListBox>
    </StackPanel>
  </Grid>
</Window>

當然,我們也可以使用 CSS 那樣的選擇器來指定模板的應用類型,而不是在 ListBox 上設置 ItemTemplate 屬性。

<Window x:Class="Learn.WPF.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:my="clr-namespace:Learn.WPF"
  Title="Window1">
  <Window.Resources>
    <my:PersonalList x:Key="personals" >
      <my:Personal Name="Tom" Age="10" Sex="Male" />
      <my:Personal Name="Mary" Age="15" Sex="Female" />
      <my:Personal Name="Jack" Age="12" Sex="Male" />
    </my:PersonalList>

    <DataTemplate DataType="{x:Type my:Personal}">
      <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Path=Name}" />
        <TextBlock>,</TextBlock>
        <TextBlock Text="{Binding Path=Age}" />
        <TextBlock>,</TextBlock>
        <TextBlock Text="{Binding Path=Sex}" />
      </StackPanel>
    </DataTemplate>
  </Window.Resources>
  <Grid>
    <StackPanel DataContext="{StaticResource personals}">
      <ListBox x:Name="listbox1" ItemsSource="{Binding}">
      </ListBox>
    </StackPanel>
  </Grid>
</Window>

通過 DataType="{x:Type my:Personal}" 我們就可以讓所有使用 Personal 對象的地方自動使用這個模板設置。

利用數據模板,我們還可以做出復雜的效果來,比如根據 Personal.Sex 來顯示一個不同顏色的邊框。類似的做法在 WinForm 似乎很麻煩,現在只需做些簡單的設置即可。

<Window x:Class="Learn.WPF.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:my="clr-namespace:Learn.WPF"
  Title="Window1">
  <Window.Resources>
    <my:PersonalList x:Key="personals" >
      <my:Personal Name="Tom" Age="10" Sex="Male" />
      <my:Personal Name="Mary" Age="15" Sex="Female" />
      <my:Personal Name="Jack" Age="12" Sex="Male" />
    </my:PersonalList>
    <DataTemplate DataType="{x:Type my:Personal}">
      <Border x:Name="border1" BorderBrush="Red" BorderThickness="1" Padding="5" Margin="5">
        <StackPanel Orientation="Horizontal">
          <TextBlock Text="{Binding Path=Name}" />
          <TextBlock>,</TextBlock>
          <TextBlock Text="{Binding Path=Age}" />
          <TextBlock>,</TextBlock>
          <TextBlock Text="{Binding Path=Sex}" />
        </StackPanel>
      </Border>

      <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding Path=Sex}">
          <DataTrigger.Value>Male</DataTrigger.Value>
          <Setter TargetName="border1" Property="BorderBrush" Value="Blue" />
        </DataTrigger>
      </DataTemplate.Triggers>
    </DataTemplate>
  </Window.Resources>
  <Grid>
    <StackPanel DataContext="{StaticResource personals}">
      <ListBox x:Name="listbox1" ItemsSource="{Binding}">
      </ListBox>
    </StackPanel>
  </Grid>
</Window>

首先,我們在數據模板中增加了一個 Border,默認顏色是紅色。然後利用觸發器,當 Personal.Sex == Male 時,將邊框顏色設置為藍色。

7. 值轉換器

某些時候,我們需要對綁定的源值進行類型或者顯示格式轉換,那麼可以采用值轉換器達到這個目的。比如我們可以將上面的 Sex 轉換成 "男"、"女" 來顯示。

Window1.xaml.cs

public class SexConverter : IValueConverter
{
  public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  {
    return value.ToString() == "Male" ? "男" : "女";
  }
  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  {
    throw new NotImplementedException();
  }
}

轉換器很簡單,只需實現 IValueConverter 接口即可。

Window1.xaml

<Window x:Class="Learn.WPF.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:my="clr-namespace:Learn.WPF"
  Title="Window1">
  <Window.Resources>
    <my:PersonalList x:Key="personals" >
      <my:Personal Name="Tom" Age="10" Sex="Male" />
      <my:Personal Name="Mary" Age="15" Sex="Female" />
      <my:Personal Name="Jack" Age="12" Sex="Male" />
    </my:PersonalList>
    <my:SexConverter x:Key="sexConverter" />
    <DataTemplate DataType="{x:Type my:Personal}">
      <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Path=Name}" />
        <TextBlock>,</TextBlock>
        <TextBlock Text="{Binding Path=Age}" />
        <TextBlock>,</TextBlock>
        <TextBlock Text="{Binding Path=Sex, Converter={StaticResource sexConverter}}" />
      </StackPanel>
    </DataTemplate>
  </Window.Resources>
  <Grid>
    <StackPanel DataContext="{StaticResource personals}">
      <ListBox x:Name="listbox1" ItemsSource="{Binding}">
      </ListBox>
    </StackPanel>
  </Grid>
</Window>

首先在資源中創建一個轉換器實例,然後在數據模板中使用 Binding.Converter 來指定轉換器實例即可。看看最終效果。

Convert() 有個有趣的的返回結果 "Binding.DoNothing",它的意思是 "暫時取消該綁定"。

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
  //return value.ToString() == "Male" ? "男" : "女";
  return Binding.DoNothing;
}

注意,DoNothing 和 null 並不是一回事,null 是個有效返回值。

接下來,我們試著將 Sex 轉換成 Brush 類型,以便顯示不同的顏色。

Window1.xaml.cs

public class SexToBrushConverter : IValueConverter
{
  public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  {
    return value.ToString() == "Male" ? Brushes.Blue : Brushes.Red;
  }
  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  {
    throw new NotImplementedException();
  }
}

Window1.xaml

<Window x:Class="Learn.WPF.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:my="clr-namespace:Learn.WPF"
  Title="Window1" Height="276" Width="360" WindowStartupLocation="CenterScreen">
  <Window.Resources>
    <my:PersonalList x:Key="personals" >
      <my:Personal Name="Tom" Age="10" Sex="Male" />
      <my:Personal Name="Mary" Age="15" Sex="Female" />
      <my:Personal Name="Jack" Age="12" Sex="Male" />
    </my:PersonalList>
    <my:SexToBrushConverter x:Key="sexToBrushConverter" />
    <DataTemplate DataType="{x:Type my:Personal}">
      <Border x:Name="border1" 
          BorderBrush="{Binding Path=Sex, Converter={StaticResource sexToBrushConverter}}" 
          BorderThickness="1" Padding="5" Margin="5">
        <StackPanel Orientation="Horizontal">
          <TextBlock Text="{Binding Path=Name}" />
          <TextBlock>,</TextBlock>
          <TextBlock Text="{Binding Path=Age}" />
          <TextBlock>,</TextBlock>
          <TextBlock Text="{Binding Path=Sex}" />
        </StackPanel>
      </Border>
    </DataTemplate>
  </Window.Resources>
  <Grid>
    <StackPanel DataContext="{StaticResource personals}">
      <ListBox x:Name="listbox1" ItemsSource="{Binding}">
      </ListBox>
    </StackPanel>
  </Grid>
</Window>

注意 Border.BorderBrush 屬性中的轉換器用法,結果表明轉換器達到了上面例子中數據模板觸發器同樣的效果。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved