如何根据DataGrid中的数据变化及时更改背景颜色



我在DataGrid中有它。目前,如果数据大于150,我将行的背景色更改为红色,如果数据小于150,则更改为绿色。我想做的是,如果背景颜色变化后5秒内数据没有变化,它应该会再次变为无色。我不知道该如何实现。你能帮忙吗?

我的转换器

class ChangedDataConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var val = (int)value;
return new SolidColorBrush(val > 150 ? Colors.Red : Colors.Green);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

xaml

<Syncfusion:GridTextColumn DisplayBinding="{Binding ID, Converter={StaticResource IntToHexadecimalConverter}}">
<Syncfusion:GridTextColumn.CellStyle>
<Style TargetType="Syncfusion:GridCell">
<Setter Property="Background" Value="{Binding ID, Converter={StaticResource ChangedDataConverter}}"/>
</Style>
</Syncfusion:GridTextColumn.CellStyle>
</Syncfusion:GridTextColumn>

编辑:我尝试了以下方法。我接近我想要的,但它只发生一次,因为它有一个上传的事件。我找不到应该使用哪种活动。有这样的东西吗?

<Syncfusion:GridTextColumn DisplayBinding="{Binding ID, Converter={StaticResource ByteToHexadecimalConverter}}" Width="100">
<Syncfusion:GridTextColumn.CellStyle>
<Style TargetType="Syncfusion:GridCell">
<Setter Property = "Background" Value="{Binding ID,Converter={StaticResource ChangedDataConverter}}"/>
<Style.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(DataGridRow.Background).(SolidColorBrush.Color)" 
Duration="00:00:10" 
To="Transparent"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Syncfusion:GridTextColumn.CellStyle>
</Syncfusion:GridTextColumn>

与使用故事板相同:

<DataGrid ItemsSource="{Binding Lines}"
AutoGenerateColumns="False">
<DataGrid.Resources>
<ColorAnimationUsingKeyFrames x:Key="KeyFramesAnimation"
Storyboard.TargetProperty="(DataGridCell.Background).(SolidColorBrush.Color)">
<LinearColorKeyFrame
KeyTime="0:0:0.3"
Value="Red"/>
<LinearColorKeyFrame
KeyTime="0:0:4.7"
Value="Red"/>
<LinearColorKeyFrame
KeyTime="0:0:5"
Value="Green"/>
</ColorAnimationUsingKeyFrames>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding ID}">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Background" Value="Green"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ID, Converter={StaticResource IntToBooleanConverter}}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<StaticResource ResourceKey="KeyFramesAnimation"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>

转换器:

public class IntToBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value is int valInt ? valInt > 150 : Binding.DoNothing;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}

在MVVM模式中,它可能看起来像这样:

型号:

public class LineModel : INotifyPropertyChanged
{
private int iD;
public int ID
{
get => iD;
set
{
iD = value;
OnPropertyChanged("ID");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string prop = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
}
}

ViewModel:

public class ViewModel : INotifyPropertyChanged
{
public Timer Tmr;
private bool timeOut;
public bool TimeOut
{
get => timeOut;
set
{
timeOut = value;
OnPropertyChanged();
}
}
public ObservableCollection<LineModel> Lines { get; set; }
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
TimeOut = false;
}
void LineModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
TimeOut = Lines != null && e.PropertyName == "ID";
Tmr.Enabled = true;
}
public ViewModel()
{
Tmr = new Timer(5000);
Tmr.Elapsed += OnTimedEvent;
Tmr.AutoReset = false;
var line = new LineModel() { ID = 10 };
line.PropertyChanged += LineModel_PropertyChanged;
Lines = new ObservableCollection<LineModel>() { line };
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string prop = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
}
}

转换器:

class ChangedDataConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values[0] is int valInt && values[1] is bool valTimeout)
return new SolidColorBrush(valTimeout && valInt > 150 ? Colors.Red : Colors.Green);
else return Binding.DoNothing;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}

XAML:

<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding ID}" Width="300">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Background">
<Setter.Value>
<MultiBinding Converter="{StaticResource ChangedDataConverter}">
<Binding Path="ID"/>
<Binding RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGrid}}" Path="DataContext.TimeOut"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
</DataGrid.Columns>

我修复了这个解决方案,现在它每次都能工作。但我不得不添加一个额外的类并重新定义事件。不再需要转换器。

助手类:

public static class EventMonitor
{
public static readonly RoutedEvent CustomEvent =
EventManager.RegisterRoutedEvent("Greater150", RoutingStrategy.Bubble,
typeof(RoutedEventHandler), typeof(EventMonitor));
internal static RoutedEventArgs RaiseAlarmEvent(DependencyObject target)
{
if (target is null) return null;
RoutedEventArgs args = new RoutedEventArgs { RoutedEvent = CustomEvent };
if (target is UIElement) (target as UIElement).RaiseEvent(args);
else if (target is ContentElement) (target as ContentElement).RaiseEvent(args);
return args;
}
public static DataGridCell GetDataGridCell(DataGridCellInfo cellInfo)
{
var cellContent = cellInfo.Column.GetCellContent(cellInfo.Item);
if (cellContent != null)
return (DataGridCell)cellContent.Parent;
return null;
}
}

XAML:

<DataGrid HorizontalAlignment="Left"
Height="303" Margin="30,78,0,0"
Width="300"
VerticalAlignment="Top"
ItemsSource="{Binding Lines}"
AutoGenerateColumns="False" CellEditEnding="DataGrid_CellEditEnding">
<DataGrid.Resources>
<ColorAnimationUsingKeyFrames x:Key="KeyFramesAnimation"
Storyboard.TargetProperty="(DataGridCell.Background).(SolidColorBrush.Color)">
<LinearColorKeyFrame
KeyTime="0:0:0.3"
Value="Red"/>
<LinearColorKeyFrame
KeyTime="0:0:4.7"
Value="Red"/>
<LinearColorKeyFrame
KeyTime="0:0:5"
Value="Green"/>
</ColorAnimationUsingKeyFrames>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding ID}" Width="290">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Background" Value="Green"/>
<Style.Triggers>
<EventTrigger RoutedEvent="local:EventMonitor.Greater150">
<BeginStoryboard>
<Storyboard>
<StaticResource ResourceKey="KeyFramesAnimation"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>

事件处理程序:

private void DataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
if (e.EditingElement is TextBox textBox && double.TryParse(textBox.Text, out double result) && result > 150)
{
EventMonitor.RaiseAlarmEvent(EventMonitor.GetDataGridCell((sender as DataGrid).SelectedCells[0]));
}
}

最新更新