简体   繁体   中英

WPF: How to update DataTrigger manually

Trigger doesn't update when using attached property.

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();
            }
        }
    }
}

At first, I tried "style1" code. But, "Column.local:TestClass.Flag" has an error.

So, I tried "style2" code. It has no errors.

But, font color didn't change.

How can I update DataTrigger manually?

there is a problem between your triggers target and the object you set the trigger to (in style 1). To color the headers text you need to change the following:

    <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>

and

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));
}

this sets the Flag for your ColumnHeader element. The Style.Trigger now is at your ColumnHeader and will been performed correctly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM