【问题标题】:Refreshing XAML items without using Refresh() method不使用 Refresh() 方法刷新 XAML 项目
【发布时间】:2018-10-01 05:47:16
【问题描述】:

我正在使用 C# WPF。

我试图弄清楚是否有一种方法可以更新 XAML 元素,而无需使用您在以下代码中看到的 Refresh() 方法。

现在我正在封装与通过线程和 XAML 代码在 MainWindow 内启动的 C# doPlay() 方法相关的代码。

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

   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,但是这样不再显示条形图,即从第一个发布的代码中删除这些说明:

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

这个问题和下面一个有关系:Network threads blocking the GUI,特别是指问题本身下面的cmets。

【问题讨论】:

  • 所以您正在尝试更新 CurrentStep 属性或者为什么需要刷新? Transfer 类是否实现了 INotifyPropertyChanged?

标签: c# wpf xaml refresh


【解决方案1】:

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

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

【讨论】:

  • @kitsune:您是否尝试实现 INotifyPropertyChanged 接口或发生了什么?
猜你喜欢
  • 2021-11-17
  • 2019-05-02
  • 2019-01-22
  • 2020-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-02
  • 2021-11-18
相关资源
最近更新 更多