WPF Datagrid - выделить строку при изменении данных - PullRequest
0 голосов
/ 22 сентября 2019

У меня есть эта рабочая заглушка:

XAML

<Window x:Class="WpfApp1.MainWindow"
        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:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <DataGrid ItemsSource="{Binding MyList}" AutoGenerateColumns="False" CanUserAddRows="False" GridLinesVisibility="None" HeadersVisibility="None" BorderThickness="0" ScrollViewer.VerticalScrollBarVisibility="Visible">
        <DataGrid.Columns>
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Label>
                            <TextBlock Text="{Binding Id}" />
                        </Label>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Label>
                            <TextBlock Text="{Binding TheData}" />
                        </Label>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
</Window>

Кодовый код

using System.Windows;
using WpfApp1.ViewModels;

namespace WpfApp1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            DataContext = new MainWindowVM();
            InitializeComponent();
        }
    }
}

ViewModel

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace WpfApp1.ViewModels
{
    public class MainWindowVM
    {
        Random random = new Random();
        public List<ListItemVM> MyList { get; set; } = new List<ListItemVM>
        {
            new ListItemVM(1, "Data1"),
            new ListItemVM(2, "Data2"),
            new ListItemVM(3, "Data3"),
        };

        public MainWindowVM()
        {
            // Start an infinite task that updates the data every 2 second
            // This emulates an external process that sends new data that must be displayed
            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    Task.Delay(2000).Wait();
                    var nextData = new string(Enumerable.Repeat("ABCDEFG", 10).Select(s => s[random.Next(s.Length)]).ToArray());
                    MyList[1].SetNewData(nextData);
                }
            });
        }
    }
}

Элемент ViewModel

using System.ComponentModel;

namespace WpfApp1.ViewModels
{
    public class ListItemVM : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public int Id { get; set; }
        public string TheData { get; set; }

        public ListItemVM(int id, string theData)
        {
            Id = id;
            TheData = theData;
        }

        internal void SetNewData(string nextData)
        {
            // Change data
            TheData = nextData;
            // Notify the UI of the change
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(TheData)));
        }
    }
}

Каждые 2 секунды я вижу обновление данных в пользовательском интерфейсе для второго элемента вDataGrid.

Вопрос

Я бы хотел, чтобы DataGridRow выделялся и исчезал через 1 секунду при каждом обновлении.Может кто-нибудь помочь мне достичь этого, пожалуйста?

Ответы [ 2 ]

0 голосов
/ 23 сентября 2019

Вы можете создать прикрепленное поведение, которое выполняет анимацию:

открытый статический класс Animator {частный статический readonly HashSet _rows = new HashSet ();

    public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached("Value", typeof(object),
        typeof(Animator), new PropertyMetadata(new PropertyChangedCallback(OnValuePropertyChanged)));

    public static object GetValue(DataGridRow d) => d.GetValue(ValueProperty);

    public static void SetValue(DataGridRow d, object value) => d.SetValue(ValueProperty, value);

    private static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        DataGridRow row = (DataGridRow)d;
        if (!_rows.Contains(row))
        {
            _rows.Add(row);
            row.Unloaded += Row_Unloaded;
        }
        else
        {
            ColorAnimation animation = new ColorAnimation();
            animation.From = Colors.Gray;
            animation.To = Colors.White;
            animation.Duration = new Duration(TimeSpan.FromSeconds(1));
            Storyboard.SetTarget(animation, row);
            Storyboard.SetTargetProperty(animation, new PropertyPath("Background.Color"));
            Storyboard sb = new Storyboard();
            sb.Children.Add(animation);
            sb.Begin();
        }
    }

    private static void Row_Unloaded(object sender, RoutedEventArgs e)
    {
        DataGridRow row = (DataGridRow)sender;
        _rows.Remove(row);
        row.Unloaded -= Row_Unloaded;
    }
}

Использование:

<DataGrid.ItemContainerStyle>
    <Style TargetType="DataGridRow">
        <Setter Property="local:Animator.Value" Value="{Binding TheData}" />
    </Style>
</DataGrid.ItemContainerStyle>
0 голосов
/ 22 сентября 2019

Вам нужно будет сделать что-то вроде:

  • Установить DataGrid.RowStyle на новый Style - возможно, переопределить значение по умолчанию ControlTemplate (см. этот ответ ) чтобы добавить элемент фона, вы можете «выделить»
  • Определить соответствующий Trigger в Style.Triggers - возможно, DataTrigger на основе TheData не пустой
  • Используйте триггер для запуска анимации - см. документацию msdn

Возможно, вам придется что-то сделать, чтобы отложить применение этого стиля - возможно, вам не нужны всестроки для выделения при начальной загрузке.Для этого вы можете использовать поведение Xaml , чтобы установить RowStyle после того, как Loaded сработало

...