如何在wpf中刷新ItemsControl以显示进度条动画

时间:2016-09-15 10:15:33

标签: c# wpf user-interface itemscontrol

这是我使用后台线程调用的合并算法:

 public static class MergeAlghorithm
    {


        public static void mergeSort(int[] vector, int n)
        {
            int curr_size;
            int left_start;

            for (curr_size = 1; curr_size <= n - 1; curr_size = 2 * curr_size)
            {
                for (left_start = 0; left_start < n - 1; left_start += 2 * curr_size)
                {


                    int mid_point = left_start + curr_size - 1;
                    int right_end = Math.Min(left_start + 2 * curr_size - 1, n - 1);

                    Merge(vector, left_start, mid_point, right_end);

                }
            }
        }

        public static void Merge(int[] vector, int left, int mid, int right)
        {
            int i, j, k;
            int n1 = mid - left + 1;
            int n2 = right - mid;

            int[] L = new int[150];
            int[] R = new int[150];



            for (i = 0; i < n1; i++)
            {
                L[i] = new int();
                L[i] = vector[left + i];

            }
            for (j = 0; j < n2; j++)
            {
                R[j] = new int();
                R[j] = vector[mid + 1 + j];
            }

            i = 0;
            j = 0;
            k = left;

            while (i < n1 && j < n2)
            {
                if (L[i] <= R[j])
                {
                    vector[k] = L[i];
                    var nr = L[i];
                    i++;

                }
                else
                {
                    vector[k] = R[j];
                    j++;

                }
                k++;
            }

            while (i < n1)
            {
                vector[k] = L[i];
                i++;
                k++;

            }
            while (j < n2)
            {
                vector[k] = R[j];
                j++;
                k++;

            }
        }
    }

这是我的MaiWindow代码,我填充数组并使用backgound线程调用StarMerge方法以刷新UI:

      public partial class MainWindow : Window
            {
               public static  List<Number> items = new List<Number>();     
                public int[] a { get; set; } = new int[150];
                public  MainWindow() 
                {
                    InitializeComponent();
                    Random randomNumber = new Random();
                    // populate the array with random numbers
                    for (int i = 0; i < a.Length; i++)
                    {
                        a[i] = new int();
                       a[i] = randomNumber.Next(1, 200);
                    }

                    StartMerge(a, 100);// her I start the merge alghorithm
                    for (int i = 0; i < 100; i++)
                    {
                        items.Add(new Number() { Title = $"{a[i]}", Completion = a[i] });
                     }
                    SortedNumbers.ItemsSource = items;
                }
                // using the below method I tried to run the alghorithm in a background thread
                public Thread StartMerge(int[] vector, int n)
                {
                    var thread = new Thread(() => MergeAlghorithm.mergeSort(vector, n));
                    thread.IsBackground = true;
                    thread.Start();
                    return thread;
                }

                //with this I created a List on which I have the binding
                public class Number
                {
                    public string Title { get; set; }
                   public int Completion { get; set; }
                }

            }

我在Listitems中完成绑定的XAML:

<Window x:Class="WpfApplication1.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:WpfApplication1"
        mc:Ignorable="d"
        Title=" MainWindow" Height="800" Width="400">
    <Grid Margin="10">
        <ItemsControl Name="SortedNumbers">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid Margin="5,0,0,5">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="800" />
                        </Grid.ColumnDefinitions>
                        <ProgressBar Grid.Column="1" Minimum="0" Maximum="600" Value="{Binding Completion}" />
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Grid>
 </Window>

这就是我在MainWindow中获得的:

100 progressbars

1 个答案:

答案 0 :(得分:1)

获取动画的一种简单方法是移动创建&amp;将项目列表分配到合并方法

public static void mergeSort(int[] vector, int n, ItemsControl ic)
{
  int curr_size;
  int left_start;

  for (curr_size = 1; curr_size <= n - 1; curr_size = 2 * curr_size)
  {
    for (left_start = 0; left_start < n - 1; left_start += 2 * curr_size)
    {
      int mid_point = left_start + curr_size - 1;
      int right_end = Math.Min(left_start + 2 * curr_size - 1, n - 1);

      Merge(vector, left_start, mid_point, right_end);

      List<Number> items = new List<Number>();
      for (int i = 0; i < n; i++)
      {
        items.Add(new Number() { Title = $"{vector[i]}", Completion = vector[i] });
      }
      ic.Dispatcher.Invoke(() => ic.ItemsSource = items);
    }
  }
}

请注意,每次都会创建一个新的List,否则看不会更改ItemsSource,因此GUI不会更新。

如果重新创建列表,每个循环都太耗时(可能是由于更大的数组),那么你必须更改Number类,以便它包含对你正在排序的数组的引用 - 你不能使用整数在这种情况下用于排序的数组,因为无法引用值类型。然后,您可以像现在一样在主方法中创建原始项目列表。只需确保ItemsControl被强制更新每个循环。