不使用 Refresh() 方法刷新 XAML 项目 [英] Refreshing XAML items without using Refresh() method

查看:48
本文介绍了不使用 Refresh() 方法刷新 XAML 项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是 C# WPF.

I'm using C # WPF.

我想知道是否有一种方法可以更新 XAML 元素,而无需使用您在以下代码中看到的 Refresh() 方法.

I'm trying to figure out if there's a way to update the XAML elements without having to use the Refresh() method that you see in the following code.

现在我将通过线程和 XAML 代码封装与 C# doPlay() 方法相关的代码.

Now I am encasing the codes related to the C# doPlay() method that is launched inside the MainWindow through a thread and the XAML code.

谁能建议一种无需使用 Refresh() 方法即可更新进度条的方法?

Can anyone suggest a way to update progress bars without having to use the Refresh() method?

   private void doPlay()
    {

        Transfers.Add(new Transfer(Utils.RandomString(6), Utils.RandomString(6), Transfer.Type_t.download, "Red"));
        Transfers.Add(new Transfer(Utils.RandomString(6), Utils.RandomString(6), Transfer.Type_t.download, "Blue"));
        Transfers.Add(new Transfer(Utils.RandomString(6), Utils.RandomString(6), Transfer.Type_t.download, "Yellow"));
        Transfers.Add(new Transfer(Utils.RandomString(6), Utils.RandomString(6), Transfer.Type_t.download, "Cyan"));
        Transfers.Add(new Transfer(Utils.RandomString(6), Utils.RandomString(6), Transfer.Type_t.download, "Black"));
        Transfers.Add(new Transfer(Utils.RandomString(6), Utils.RandomString(6), Transfer.Type_t.download, "Brown"));

        Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
        {
            TransfersXAML.ItemsSource = Transfers;
        }));

        Random rnd = new Random();

        for (var i = 0; i < 100 * Transfers.Count; i++)
        {
            var next = rnd.Next(0, Transfers.Count);
            mre.WaitOne();
            int index =  next;

            if (Transfers[index].CurrentStep < 100)
            {
                Thread.Sleep(100);
                Transfers[index].CurrentStep++;

                Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
                {
                    TransfersXAML.Items.Refresh();
                }));

            }
            else i--;
        }
     }

XAML 相关代码:

        <UniformGrid x:Name="DownLeftPanel" Grid.Column="2" Grid.Row="2">
            <ListBox x:Name="TransfersXAML" HorizontalContentAlignment="Stretch" ItemsSource="{Binding Transfers}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <ProgressBar Height="30" Minimum="0" Maximum="{Binding NSteps}"
                                     Value="{Binding CurrentStep}" Foreground="{Binding Color}" />
                    </DataTemplate>
                </ListBox.ItemTemplate>
                <ListBox.ContextMenu>
                    <ContextMenu>
                        <MenuItem Header="Get info" Click="GetTransferInfoClick" />
                        <MenuItem Header="Cancel" Click="CancelTransferClick" />
                    </ContextMenu>
                </ListBox.ContextMenu>
            </ListBox>
        </UniformGrid>

我试图从BeginInvoke中简单地删除Action,但这样就不再显示条形,即从第一次发布的代码中删除这些说明:

I tried to simply remove the Action from BeginInvoke, but in this way the bars are no longer displayed, that is, removing these instructions from the first posted code:

Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
     TransfersXAML.Items.Refresh();
}));

<小时>

此问题与以下问题有关:网络线程阻塞GUI,特别是指问题本身下方的评论.


This question is related to the following one: Network threads blocking the GUI, in particular, referring to the comments below the question itself.

推荐答案

如果 Transfers 类实现了 INotifyPropertyChanged 接口并在 CurrentStep 的 setter 中引发 PropertyChanged 事件 属性,您可以简单地在后台线程上设置此属性,而无需调用 Refresh() 方法:

If the Transfers class implements the INotifyPropertyChanged interface and raise the PropertyChanged event in the setter of the CurrentStep property, you could simply set this property on the background thread without ever calling the Refresh() method:

for (var i = 0; i< 100 * Transfers.Count; i++)
{
    var next = rnd.Next(0, Transfers.Count);
    mre.WaitOne();
    int index = next;

    if (Transfers[index].CurrentStep < 100)
    {
        Thread.Sleep(100);
        Transfers[index].CurrentStep++;
    }
    else i--;
}

这篇关于不使用 Refresh() 方法刷新 XAML 项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆