2016-12-04 31 views
0

使用附加屬性時,觸發器不會更新。WPF:如何手動更新DataTrigger

Window1.xaml

<Window x:Class="proj1.Window1" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:proj1" 
     mc:Ignorable="d" 
     Title="Window1" Height="300" Width="300"> 
    <Window.Resources> 
     <Style TargetType="ListView" x:Key="style1"> 
      <Setter Property="View"> 
       <Setter.Value> 
        <GridView> 
         <GridViewColumn Header="1" DisplayMemberBinding="{Binding one}" Width="100" /> 
         <GridViewColumn Header="2" DisplayMemberBinding="{Binding two}" Width="100" /> 
        </GridView> 
       </Setter.Value> 
      </Setter> 
      <EventSetter Event="GridViewColumnHeader.Click" Handler="ColumnHeader_Click"/> 
      <Style.Triggers> 
       <!-- 
       <Trigger Property="Column.local:TestClass.Flag" Value="True"> 
        <Setter Property="Foreground" Value="Red" /> 
       </Trigger> 
       --> 
      </Style.Triggers> 
     </Style> 
     <Style TargetType="ListView" x:Key="style2"> 
      <Setter Property="View"> 
       <Setter.Value> 
        <GridView> 
         <GridViewColumn Header="1" DisplayMemberBinding="{Binding one}" Width="100" /> 
         <GridViewColumn Header="2" DisplayMemberBinding="{Binding two}" Width="100" /> 
        </GridView> 
       </Setter.Value> 
      </Setter> 
      <EventSetter Event="GridViewColumnHeader.Click" Handler="ColumnHeader_Click"/> 
      <Style.Triggers> 
       <DataTrigger Binding="{Binding Column, RelativeSource={RelativeSource Self}, Converter={x:Static local:TestClass.Converter}}" Value="True"> 
        <Setter Property="Foreground" Value="Red" /> 
       </DataTrigger> 
      </Style.Triggers> 
     </Style> 
    </Window.Resources> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition/> 
      <RowDefinition/> 
     </Grid.RowDefinitions> 

     <ListView Grid.Row="0" Style="{StaticResource style1}" ItemsSource="{Binding items}" /> 
     <ListView Grid.Row="1" Style="{StaticResource style2}" ItemsSource="{Binding items}" /> 

    </Grid> 
</Window> 

Window1.xaml.cs

using System; 
using System.Collections.Generic; 
using System.Globalization; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Shapes; 

namespace proj1 
{ 
    public partial class Window1 : Window 
    { 
     public Window1() 
     { 
      InitializeComponent(); 

      // set dummy data 
      this.DataContext = new 
      { 
       items = new[] 
       { 
        new { 
         one = "A", 
         two = "a", 
        }, 
        new { 
         one = "B", 
         two = "b", 
        }, 
        new { 
         one = "C", 
         two = "c", 
        }, 
        new { 
         one = "D", 
         two = "d", 
        }, 
       } 
      }; 
     } 

     /// <summary> 
     /// cannot change! 
     /// </summary> 
     /// <param name="sender"></param> 
     /// <param name="e"></param> 
     private void ColumnHeader_Click(object sender, RoutedEventArgs e) 
     { 
      var column_header = e.OriginalSource as GridViewColumnHeader; 

      if (column_header == null) return; 

      var column = column_header.Column; 

      if (column == null) return; 

      TestClass.Setflag(column, !TestClass.GetFlag(column)); 

      // debug print 
      Console.WriteLine($"{column_header.Content}/{TestClass.GetFlag(column)}"); 
     } 
    } 

    /// <summary> 
    /// Define 'Flag' AttachedProprety and IValueCoverter which pick 
    /// 'Flag' AttachedProperty from a DependencyObject 
    /// </summary> 
    public class TestClass 
    { 
     public static bool GetFlag(DependencyObject obj) 
     { 
      return (bool)obj.GetValue(FlagProperty); 
     } 

     public static void Setflag(DependencyObject obj, bool value) 
     { 
      obj.SetValue(FlagProperty, value); 
     } 

     // Using a DependencyProperty as the backing store for flag. This enables animation, styling, binding, etc... 
     public static readonly DependencyProperty FlagProperty = 
      DependencyProperty.RegisterAttached("Flag", typeof(bool), typeof(TestClass), new PropertyMetadata(false)); 

     public static IValueConverter Converter => new GetFlagConverter(); 

     public class GetFlagConverter : IValueConverter 
     { 
      public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
      { 
       var dobj = value as DependencyObject; 
       if (dobj == null) 
       { 
        return false; 
       } 

       return GetFlag(dobj); 
      } 

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

起初,我試圖 「樣式1」 代碼。但是,「Column.local:TestClass.Flag」有錯誤。

所以,我嘗試了「style2」代碼。它沒有錯誤。

但是,字體顏色沒有改變。

如何手動更新DataTrigger

+1

嘗試發佈儘可能少的代碼來模擬相同的場景。它會給你一個更快的答案,並且會更容易閱讀。 – MYGz

回答

0

觸發器目標和您設置觸發器的對象(在樣式1中)之間存在問題。顏色標題文本您需要更改如下:

<Style x:Key="style1" TargetType="ListView"> 
    <Setter Property="View"> 
     <Setter.Value> 
      <GridView> 
       <GridViewColumn Width="100" 
           DisplayMemberBinding="{Binding one}" 
           Header="1"> 
        <GridViewColumn.HeaderContainerStyle> 
         <Style TargetType="GridViewColumnHeader"> 
          <Style.Triggers> 
           <Trigger Property="local:TestClass.Flag" Value="True"> 
            <Setter Property="Foreground" Value="Red" /> 
           </Trigger> 
          </Style.Triggers> 
         </Style> 
        </GridViewColumn.HeaderContainerStyle> 
       </GridViewColumn> 
       <GridViewColumn Width="100" 
           DisplayMemberBinding="{Binding two}" 
           Header="2" > 
        <GridViewColumn.HeaderContainerStyle> 
         <Style TargetType="GridViewColumnHeader"> 
          <Style.Triggers> 
           <Trigger Property="local:TestClass.Flag" Value="True"> 
            <Setter Property="Foreground" Value="Red" /> 
           </Trigger> 
          </Style.Triggers> 
         </Style> 
        </GridViewColumn.HeaderContainerStyle> 
       </GridViewColumn> 
      </GridView> 
     </Setter.Value> 
    </Setter> 
    <EventSetter Event="GridViewColumnHeader.Click" Handler="ColumnHeader_Click" /> 
</Style> 

private void ColumnHeader_Click(object sender, RoutedEventArgs e) 
{ 
    var column_header = e.OriginalSource as GridViewColumnHeader; 

    if (column_header == null) return; 

    TestClass.Setflag(column_header, !TestClass.GetFlag(column_header)); 
} 

這臺Flag爲您ColumnHeader元素。 Style.Trigger現在在您的ColumnHeader,並將正確執行。

+0

由於其他原因,'flag'必須設置爲'column'。 在這種情況下,我是否必須同時設置'column'和'header'? 我想只爲'column'設置'flag'(如果可以的話)。 – blz