Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I'm using C # WPF.

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.

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.

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

The XAML relative code:

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

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

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
121 views
Welcome To Ask or Share your Answers For Others

1 Answer

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...