WPF觸發器(Trigger) - DataTrigger

官方文檔中對DataTrigger的介紹

Represents a trigger that applies property values or performs actions when the bound data meets a specified condition.markdown

某詞典的翻譯:
當綁定的數據知足指定的條件時,應用(指定的)屬性或執行操做的觸發器app

下面我演示一遍官方文檔中的示例,根據官網的描述,創建實體類,而後編寫前臺代碼

  • 先來張效果圖函數

    • 經過DataTrigger,將省份爲江蘇省的Item項的文字顏色設置成了紅色;
    • 而後又經過MultoDataTrigger,將省份爲江西省市爲南昌的Item設置的背景設置成淺藍色
    • 關鍵部分代碼:
      <Page.Resources>
          <dataTrigger:Places x:Key="Places"/>
          <Style TargetType="ListBoxItem">
              <Style.Triggers>
                  <DataTrigger Binding="{Binding Path=Province}" Value="江蘇省">
                      <Setter Property="Foreground"  Value="Red"/>
                  </DataTrigger>
                  <MultiDataTrigger>
                      <MultiDataTrigger.Conditions>
                          <Condition Binding="{Binding Path=Province}" Value="江西省"/>
                          <Condition Binding="{Binding Path=Name}" Value="南昌"/>
                      </MultiDataTrigger.Conditions>
                      <Setter Property="Background" Value="Cyan"/>
                  </MultiDataTrigger>
              </Style.Triggers>
          </Style>
          <DataTemplate x:Key="PlaceTemplate" DataType="{x:Type dataTrigger:Place}">
              <StackPanel Orientation="Horizontal">
                  <TextBlock Text="{Binding Province,Mode=OneWay,StringFormat={}{0}- - &#160;&#160;}"/>
                  <TextBlock Text="{Binding Name,Mode=OneWay}"/>
              </StackPanel>
          </DataTemplate>
      </Page.Resources>
      <Grid>
          <ListBox Margin="20 30" 
                   MaxWidth="300" MaxHeight="250"
                   ItemsSource="{StaticResource Places}"
                   ItemTemplate="{StaticResource PlaceTemplate}">
          </ListBox>
      </Grid>
  • 新建一個測試項目:測試

  • 添加兩個類:spa

    • Place
    • Places
      namespace Demo.DataTrigger
      {
          public class Place
          {
              public string Name { get; set; }
              public string Province { get; set; }
      
              public Place(string name,string province)
              {
                  Name = name;
                  Province = province;
              }
          }
      }
      
      
      using System.Collections.ObjectModel;
      namespace Demo.DataTrigger
      {
          public class Places:ObservableCollection<Place>
          {
              public Places()
              {
                  Add(new Place("南京", "江蘇省"));
                  Add(new Place("寧波", "浙江省"));
                  Add(new Place("蘇州", "江蘇省"));
                  Add(new Place("南通", "江蘇省"));
                  Add(new Place("深圳", "廣州省"));
                  Add(new Place("蕪湖", "安徽省"));
                  Add(new Place("東菀", "廣東省"));
                  Add(new Place("無錫", "江蘇省"));
                  Add(new Place("南昌", "江西省"));
              }
          }
      }
  • xaml代碼翻譯

    <Page.Resources>
        <dataTrigger:Places x:Key="Places"/>
        <Style TargetType="ListBoxItem">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=Province}" Value="江蘇省">
                    <Setter Property="Foreground"  Value="Red"/>
                </DataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding Path=Province}" Value="江西省"/>
                        <Condition Binding="{Binding Path=Name}" Value="南昌"/>
                    </MultiDataTrigger.Conditions>
                    <Setter Property="Background" Value="Cyan"/>
                </MultiDataTrigger>
            </Style.Triggers>
        </Style>
    
        <DataTemplate x:Key="PlaceTemplate" DataType="{x:Type dataTrigger:Place}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Province,Mode=OneWay,StringFormat={}{0}- - &#160;&#160;}"/>
                <TextBlock Text="{Binding Name,Mode=OneWay}"/>
            </StackPanel>
        </DataTemplate>
    </Page.Resources>
    
    <ListBox Margin="20 30" 
            MaxWidth="300" MaxHeight="250"
            ItemsSource="{StaticResource Places}"
            ItemTemplate="{StaticResource PlaceTemplate}">
    </ListBox>

下面的一個例子是我在項目中遇到的

Image控件的Source屬性經過數據綁定到後臺屬性的一個圖片的路徑,當後臺屬性爲null時,默認一個路徑提供給Image控件,恰巧這兩天看到一個DataTrigger,就想着用它來實現,結果經歷了一番周折,最終經過一個Converter值轉化器和DataTrigger配合實現了,下面演示代碼;code

先看前臺xaml代碼:
<StackPanel Orientation="Horizontal">
    <StackPanel.Resources>
        <dataTrigger:PathValidateConverter x:Key="Converter"></dataTrigger:PathValidateConverter>
    </StackPanel.Resources>
    <Image>
        <Image.Style>
            <Style TargetType="Image">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=ThumbnailPath,Mode=OneWay,Converter={StaticResource Converter}}"
                                    Value="False">
                        <Setter Property="Source" Value="/Resources/Images/icons8-thumbnails-80.png"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Path=ThumbnailPath,Mode=OneWay,Converter={StaticResource Converter}}"
                                    Value="True">
                        <Setter Property="Source" Value="E:\\Media\\Images\\Src\\s.png"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Image.Style>
    </Image>
    <CheckBox Content="設置ThumbnailPath爲有效的路徑值" 
                Checked="CheckBox_Checked" Unchecked="CheckBox_Unchecked"/>
</StackPanel>

而後看一下那個簡單的值轉換器,就是經過File.Exists()方法來判斷文件路徑是否合法,不合法則返回false:orm

PathValidatorConverter
using System;
using System.Globalization;
using System.IO;
using System.Windows.Data;

namespace Demo.DataTrigger
{
    class PathValidateConverter:IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null) return false;
            if (value.GetType() != typeof(string)) throw new ArgumentOutOfRangeException(nameof(value));

            return File.Exists((string) value);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

因爲這個項目我只是用來演示的,因此就懶得去創建ViewModel,直接把代碼xaml的隱藏類做爲DataContext,後臺代碼中定義一個依賴屬性來表示圖片路徑:blog

public string ThumbnailPath 
{
    get => (string)GetValue(MyPropertyProperty);
    set => SetValue(MyPropertyProperty, value);
}

// Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyPropertyProperty =
    DependencyProperty.Register(nameof(ThumbnailPath), typeof(string), typeof(Demo),
    new FrameworkPropertyMetadata(null));

還有兩個函數處理前臺CheckBox的Checked和UnChecked事件:事件

private void CheckBox_Checked(object sender, RoutedEventArgs e)
        {
            ThumbnailPath = @"E:\\Media\\Images\\Src\\s.png";
        }

        private void CheckBox_Unchecked(object sender, RoutedEventArgs e)
        {
            ThumbnailPath = null;
        }

當CheckedBox被選中時,或將ThumbnailPath設置成一個圖片的絕對路徑,而沒被選中時,ThumbnailPath則被置爲null

最終效果以下:

  • 不選中CheckBox時:
  • 選中時:

總結,DataTrigger能夠在某些數據發生改變時設置一些UI的樣式,應該還有很多應用,WPF裏的東西感受比較多,有些東西用完不記錄東西,容易遺忘,因此多記錄如下老是好的.另外,各位大蝦,大家若是有啥思路實現上面第二個例子的效果,歡迎指教....我暫時就先這麼用了

相關文章
相關標籤/搜索