Как добавить задержку, когда мышь покидает текущую ячейку в таблице 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();
        }

    }

person Darth Coder    schedule 15.07.2014    source источник
comment
это ячейка datagrid?   -  person pushpraj    schedule 15.07.2014
comment
Нет, это таблица, нарисованная в FlowDocument.   -  person Darth Coder    schedule 15.07.2014


Ответы (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>

попробуйте приведенный выше пример, это изменит цвет на зеленый, когда мышь войдет, и медленно станет серебристым при выходе. также возможно непрерывное проникновение мыши в другие ячейки или даже в одну и ту же ячейку


Обновить

вот как вы можете сделать то же самое в С#

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

результат

результат

самое приятное, что анимация работает безупречно

person pushpraj    schedule 15.07.2014
comment
Я не могу использовать XAML, потому что я сгенерировал все (таблицу и все остальное в пользовательском интерфейсе) с помощью кода C#. Таким образом, эффекты наведения также должны быть выполнены с использованием кода C#. Можете ли вы дать мне решение для этого? - person Darth Coder; 15.07.2014
comment
Я обновил ответ. просто используйте код и удалите любой таймер и т. д. - person pushpraj; 15.07.2014
comment
Я использовал его, ошибка: Не удалось найти имя типа или пространства имен «ColorAnimation».... Как мне это исправить? Это под системой или что-то в этом роде? - person Darth Coder; 15.07.2014
comment
Исправлена. Используется System.Windows.Media.Animation.ColorAnimation Спасибо! - person Darth Coder; 15.07.2014
comment
В то время как это выполняет анимацию, это удерживает мой основной поток пользовательского интерфейса в течение 1 секунды, что означает, что при переходе к новой ячейке в таблице наблюдается видимое отставание, ожидая, пока цвет ранее наведенной ячейки вернется к серебру и будет иметь цвет вновь наведенная ячейка становится зеленой. Я думаю, мне нужен отдельный поток для управления анимацией? - person Darth Coder; 15.07.2014
comment
сама анимация использует отдельный поток, однако обновления выполняются только в потоке пользовательского интерфейса. Вы можете опубликовать рабочий пример своего кода, давайте посмотрим, как мы можем улучшить производительность. - person pushpraj; 15.07.2014
comment
Я попытался несколькими способами, кажется, что мы ограничены рамками здесь. не анимация отстает, а события отстают. просто хотел уточнить у вас, является ли FlowDocument необходимостью? - person pushpraj; 15.07.2014
comment
На самом деле я намеревался использовать Canvas вместо этого, но не смог добавить созданную таблицу (не могу преобразовать из Windows.Document в элемент пользовательского интерфейса). Таким образом, вместо этого я использовал потоковый документ. Это влияет на лаги? - person Darth Coder; 15.07.2014
comment
Давайте продолжим обсуждение в чате. - person pushpraj; 15.07.2014