0

the problem is the wpf not save changes Only after the end of the event

//code
private void button1_Click(object sender, RoutedEventArgs e)
{
    for (int ii = 0; ii <= 5; ii++)
    {
        Rectangle rectr = (Rectangle)FindName("rect" + ii);
        rectr.Fill = Brushes.Black;
        // need some thing to save changes here 
        Thread.Sleep(100);
    }

}

the question is how to save changes

all i need change the background color of each rectangle and sleep some time then change the next rectangle

Ahmed Samir
  • 53
  • 10

2 Answers2

0

Try something like that:

XAML file:

<Window x:Class="RectangleNS.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="30" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <Button Content="Change Color" Click="Button_Click" />

        <StackPanel Grid.Row="1" >
            <Rectangle Name="rect1" Fill="Red" Height="50" />
            <Rectangle Name="rect2" Fill="Yellow" Height="50" />
            <Rectangle Name="rect3" Fill="Green" Height="50" />
            <Rectangle Name="rect4" Fill="AliceBlue" Height="50" />
            <Rectangle Name="rect5" Fill="DarkTurquoise" Height="50" />
        </StackPanel>        
    </Grid>
</Window>

Code-behind file:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Threading;

namespace RectangleNS
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            BackgroundWorker bw = new BackgroundWorker();

            Grid grid = (Grid)(sender as Button).Parent;

            bw.DoWork += (o, ee) => 
            {
                for (int i = 1; i <= 5; i++)
                {
                    Rectangle rectr = null;
                    Application.Current.Dispatcher.Invoke((Action)(() => { rectr = VTHelper.FindVisualChildByName<Rectangle>(grid, "rect" + i); }));
                    Application.Current.Dispatcher.Invoke((Action)(() => { rectr.Fill = Brushes.Black; }));                 
                    Thread.Sleep(100);
                } 
            };

            bw.RunWorkerAsync();
        }
    }

    public static class VTHelper
    {
        public static T FindVisualChildByName<T>(DependencyObject parent, string name) where T : DependencyObject
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
            {
                var child = VisualTreeHelper.GetChild(parent, i);
                string controlName = child.GetValue(Control.NameProperty) as string;
                if (controlName == name)
                {
                    return child as T;
                }
                else
                {
                    T result = FindVisualChildByName<T>(child, name);
                    if (result != null)
                        return result;
                }
            }
            return null;
        }
    }
}
kmatyaszek
  • 19,016
  • 9
  • 60
  • 65
0

Button_Click is invoked by the UI thread, and you should not do anything requiring more than a few miliseconds in it, let it be sleeping for 100 millisconds. Messages are not processed during that time, your interface is unresponsive, and your application is considered "hung" by the system.

So, that long processing task should be handled by another thread. Replace your code with this and it should work for you -

for (int ii = 0; ii <= 5; ii++)
            {
                BackgroundWorker backgroundWorker = new BackgroundWorker();
                backgroundWorker.DoWork += (s, args) =>
                    {
                        args.Result = (int)args.Argument;
                        Thread.Sleep(100);
                    };
                backgroundWorker.RunWorkerCompleted += (s, args) =>
                {
                    int value = (int)args.Result;
                    Rectangle rectr = (Rectangle)FindName("rect" + value);
                    rectr.Fill = Brushes.Black;
                };
                backgroundWorker.RunWorkerAsync(ii);
            }
Rohit Vats
  • 79,502
  • 12
  • 161
  • 185