Как добавить задержку, когда мышь покидает текущую ячейку в таблице WPF?
Мне нужна помощь с написанием кода задержки, чтобы добавить эффект к моему mouse_hover, когда он оставляет ячейку в таблице. Когда мышь входит в ячейку, она окрашивает границу в зеленый. Когда он покидает ячейку, цвет должен медленно угасать до своего первоначального цвета (серебро) в течение 1 секунды. В течение этого времени пользователь должен непрерывно перемещаться по другим ячейкам. Вот что я пробовал до сих пор:
//cell hover effects
System.Timers.Timer timer = new System.Timers.Timer(1);
TableCell tc;
private void cell_MouseEnter(object sender, MouseEventArgs e)
{
tc = (TableCell)sender;
tc.BorderBrush = Brushes.Green;
}
private void cell_MouseLeave(object sender, MouseEventArgs e)
{
tc = (TableCell)sender;
timer.Start();
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
tc.BorderBrush = Brushes.Silver;
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
tc.BorderBrush = Brushes.Silver;
timer.Stop();
}
Этот код выдает ошибку при переходе в другую ячейку, так как другой поток работает с текущей ячейкой. Может кто-нибудь помочь мне исправить это или показать лучший способ добиться этого?
Нужно решение на C#, а не XAML
Полный код для справки:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
InitTable();
}
private void InitTable()
{
//Canvas task1Canvas = new Canvas();
Table symptomTable = new Table();
//task1Canvas.Children.Add(symptomTable);
FlowDocument flowDoc = new FlowDocument();
flowDoc.Blocks.Add(symptomTable);
//symptomTable.CellSpacing = 128;
// Create N columns and add them to the table's Columns collection.
int numOfCols = 14;
for (int i = 0; i < numOfCols; i++)
{
symptomTable.Columns.Add(new TableColumn());
symptomTable.Columns[i].Width = new GridLength(128); //cell width
}
// Create and add an empty TableRowGroup Rows.
symptomTable.RowGroups.Add(new TableRowGroup());
//Add the first row to the table
symptomTable.RowGroups[0].Rows.Add(new TableRow());
//Configure the table head row
TableRow currentRow = symptomTable.RowGroups[0].Rows[0];
// Add the header row with content,
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("August"))));
for (int n = 1; n <= 13; n++)
currentRow.Cells.Add(new TableCell(new Paragraph(new Run((10+n).ToString()))));
//Add the remaining rows
int row = 1;
string[] rowHeaders = new string[] { "river", "explosion", "flu", "airport", "chills", "morning", "tech", "truck", "cold" };
foreach (string label in rowHeaders)
{
symptomTable.RowGroups[0].Rows.Add(new TableRow());
//Configure the table head row
currentRow = symptomTable.RowGroups[0].Rows[row++];
// Add the header row with content,
currentRow.Cells.Add(new TableCell(new Paragraph(new Run(label))));
for (int n = 1; n <= 13; n++)
currentRow.Cells.Add(new TableCell(new Paragraph(new Run(""))));
for (int n = 1; n < currentRow.Cells.Count; n++)
{
currentRow.Cells[n].BorderThickness = new Thickness(3, 3, 3, 3);
currentRow.Cells[n].BorderBrush = Brushes.Silver;
currentRow.Cells[n].MouseEnter += new MouseEventHandler(cell_MouseEnter);
if(label != "chills")
currentRow.Cells[n].MouseLeave += new MouseEventHandler(cell_MouseLeave);
}
}
//Add the given flow document to the window
this.Content = flowDoc;
}
//cell hover effects
System.Timers.Timer timer = new System.Timers.Timer(1);
TableCell tc;
Thread animatationThread;
private void cell_MouseEnter(object sender, MouseEventArgs e)
{
tc = (TableCell)sender;
//Color colour = System.Drawing.ColorTranslator.FromHtml("#66CC00");
Color greenShade = (Color)ColorConverter.ConvertFromString("#FF66CC00");
BrushConverter converter = new BrushConverter();
Brush brush = converter.ConvertFromString("#FF66CC00") as Brush;
tc.BorderBrush = brush;
//System.Threading.Thread animationThread = new System.Threading.Thread();
//animatationThread = new Thread(new ThreadStart(brush.BeginAnimation(SolidColorBrush.ColorProperty, new System.Windows.Media.Animation.ColorAnimation(Colors.Silver, TimeSpan.FromSeconds(1)))));
//brush.BeginAnimation(SolidColorBrush.ColorProperty, new System.Windows.Media.Animation.ColorAnimation(Colors.Silver, TimeSpan.FromSeconds(1)));
}
private void cell_MouseLeave(object sender, MouseEventArgs e)
{
//TableCell tc;
tc = (TableCell)sender;
//timer.Start();
//timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
tc.BorderBrush = Brushes.Silver;
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
tc.BorderBrush = Brushes.Silver;
timer.Stop();
}
}
1 ответ
Вам может не потребоваться какой-либо код для достижения того же самого, вы можете сделать это через XAML декларативно
Я использовал анимацию для достижения желаемого результата
пример
<DataGrid xmlns:sys="clr-namespace:System;assembly=mscorlib">
<DataGrid.Resources>
<Style TargetType="DataGridCell">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridCell">
<Border x:Name="border"
BorderThickness="2"
BorderBrush="Silver">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="border"
Storyboard.TargetProperty="BorderBrush.Color"
Duration="0:0:0"
To="Green" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="border"
Storyboard.TargetProperty="BorderBrush.Color"
Duration="0:0:1"
To="Silver" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding}"
Header="column" />
</DataGrid.Columns>
<sys:String>item 1</sys:String>
<sys:String>item 2</sys:String>
<sys:String>item 3</sys:String>
<sys:String>item 4</sys:String>
</DataGrid>
попробуйте пример выше, это изменит цвет на зеленый при вводе мышью и будет медленно переходить в серебристый при выходе. также возможно, чтобы мышь входила в другие ячейки или даже в одну и ту же ячейку непрерывно
Обновить
Вот как вы можете сделать то же самое в C#
private void cell_MouseLeave(object sender, MouseEventArgs e)
{
TableCell tc = (TableCell)sender;
SolidColorBrush brush = new SolidColorBrush(Colors.Green);
tc.BorderBrush = brush;
brush.BeginAnimation(SolidColorBrush.ColorProperty, new ColorAnimation(Colors.Silver, TimeSpan.FromSeconds(1)));
}
вам не нужно никакого таймера, анимация будет работать для вас и будет постепенно переходить в серебро
Обновление 2
Основываясь на вашем коде и исходя из комментариев, FlowDocument
это не необходимость, я придумаю альтернативное решение
все за кодом
private void InitTable()
{
int numOfCols = 14;
UniformGrid grid = new UniformGrid();
grid.Columns = numOfCols;
grid.Children.Add(new TextBlock() { Text = "August", FontWeight = FontWeights.Bold });
for (int n = 1; n < numOfCols; n++)
grid.Children.Add(new TextBlock() { Text = (10 + n).ToString(), FontWeight = FontWeights.Bold });
string[] rowHeaders = new string[] { "river", "explosion", "flu", "airport", "chills", "morning", "tech", "truck", "cold" };
Style cellStyle = PrepareAnimationStyle();
foreach (string label in rowHeaders)
{
grid.Children.Add(new TextBlock() { Text = label, FontWeight = FontWeights.Bold });
for (int n = 1; n < numOfCols; n++)
grid.Children.Add(new Border()
{
BorderBrush = new SolidColorBrush(Colors.Silver),
Background = Brushes.Transparent,
BorderThickness = new Thickness(3),
Style = cellStyle
});
}
this.Content = grid;
}
Style PrepareAnimationStyle()
{
Trigger animTrigger = new Trigger();
animTrigger.Property = ContentElement.IsMouseOverProperty;
animTrigger.Value = true;
ColorAnimation toGreen = new ColorAnimation((Color)ColorConverter.ConvertFromString("#FF66CC00"), TimeSpan.FromSeconds(0));
toGreen.FillBehavior = FillBehavior.HoldEnd;
ColorAnimation toSilver = new ColorAnimation(Colors.Silver, TimeSpan.FromSeconds(1));
Storyboard sbEnter = new Storyboard();
Storyboard.SetTargetProperty(toGreen, new PropertyPath("BorderBrush.Color"));
sbEnter.Children.Add(toGreen);
Storyboard sbExit = new Storyboard();
Storyboard.SetTargetProperty(toSilver, new PropertyPath("BorderBrush.Color"));
sbExit.Children.Add(toSilver);
animTrigger.EnterActions.Add(new BeginStoryboard() { Storyboard = sbEnter });
animTrigger.ExitActions.Add(new BeginStoryboard() { Storyboard = sbExit });
Style cellStyle = new Style();
cellStyle.Triggers.Add(animTrigger);
return cellStyle;
}
результат
лучшая часть анимации работает без нареканий