Recently I’ve been working on a project where I need to change the column value of a listview like when the user clicks on the start button, it changes the whole column text to ‘Searching,’ and after that, each cell of the column changes its text to completed, retry, captcha, etc. how can I achieve this again I’m using listView here is what my list looks like enter image description here
when I click the button the waiting should be changed to searching and after the delay of each cell should change to completed, reserved, retry, etc. There is no logic behind it just to change the random text here is what I’m looking for enter image description here
You can see there is a certain amount of delay between every cell change
Code for delay don't have much knowledge about tasks and threads
Private Async Sub btnStart_Click(sender As Object, e As RoutedEventArgs) Handles btnStart.Click
Await BadLoopAsync(myType)
End Sub
Public Async Function Searching(item As Custom_Type) As Task
item.Status1 = "Searching"
item.BackColor1 = New SolidColorBrush(Colors.Black)
Await Task.Delay(1000)
End Function
Public Async Function BadLoopAsync(ByVal thingsToLoop As IEnumerable(Of Custom_Type)) As Task
For Each thing In thingsToLoop
Await Searching(thing)
Next
End Function
Window Code
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Me.DataContext = Me
Dim type1 = New Custom_Type("site.org", "Snow Globe - Coke Bottel", "Luminati", "[email protected]", "$1.22", "Waiting", New SolidColorBrush(Color.FromRgb(44, 184, 185)))
myType = New ObservableCollection(Of Custom_Type)()
For i = 0 To 10
myType.Add(type1)
Next
myType.Add(type1)
listView.ItemsSource = myType
Private Async Function ChangeItemsStateAsync(ByVal state As String, ByVal color As Color, ByVal isDelayed As Boolean) As Task
Dim randomGenerator = New Random()
Dim coloredItems As List(Of Custom_Type) = Me.myType.ToList()
While coloredItems.Any()
Dim randomIndex As Integer = randomGenerator.[Next](0, coloredItems.Count - 1)
Dim item As Custom_Type = coloredItems(randomIndex)
coloredItems.RemoveAt(randomIndex)
item.Status1 = state
item.BackColor1 = New SolidColorBrush(color)
If isDelayed Then
Dim delayInMilliseconds As Integer = randomGenerator.[Next](125, 3000)
Await Task.Delay(delayInMilliseconds)
End If
End While
End Function
Custom_Type.class
Imports System.ComponentModel Imports System.Runtime.CompilerServices
Public Class Custom_Type Implements INotifyPropertyChanged Private Property site As String Private Property item As String Private Property proxy As String Private Property profile As String Private Property dollars As String Private Property status As String
Public Property backColor As SolidColorBrush
Sub New(site As String, item As String, proxy As String, profile As String, dollars As String, status As String, backColor As SolidColorBrush)
Me.site = site
Me.item = item
Me.proxy = proxy
Me.profile = profile
Me.dollars = dollars
Me.status = status
Me.backColor = backColor
End Sub
Sub New(status As String, backColor As SolidColorBrush)
Me.status = status
Me.backColor = backColor
End Sub
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Private Sub NotifyPropertyChanged(<CallerMemberName()> Optional ByVal propertyName As String = Nothing)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
Sub New()
End Sub
Public Property Status1 As String
Get
Return Me.status
End Get
Set(value As String)
Me.status = value
NotifyPropertyChanged("Status1")
End Set
End Property
Public Property Item1 As String
Get
Return Me.item
End Get
Set(value As String)
Me.item = value
NotifyPropertyChanged("Item1")
End Set
End Property
Public Property Proxy1 As String
Get
Return Me.proxy
End Get
Set(value As String)
Me.proxy = value
NotifyPropertyChanged("Proxy1")
End Set
End Property
Public Property Profile1 As String
Get
Return Me.profile
End Get
Set(value As String)
Me.profile = value
NotifyPropertyChanged("Profile1")
End Set
End Property
Public Property Dollars1 As String
Get
Return Me.dollars
End Get
Set(value As String)
Me.dollars = value
NotifyPropertyChanged("Dollars1")
End Set
End Property
Public Property Site1 As String
Get
Return Me.site
End Get
Set(value As String)
Me.site = value
NotifyPropertyChanged("Site1")
End Set
End Property
Public Property BackColor1 As SolidColorBrush
Get
Return Me.backColor
End Get
Set(value As SolidColorBrush)
Me.backColor = value
NotifyPropertyChanged("BackColor1")
End Set
End Property
End Class ListView Code
<ListView Grid.IsSharedSizeScope="True" Grid.Row="1" Grid.Column="1" x:Name="listView" Margin="25,10,0,60" Background="Transparent"
BorderThickness="0" ItemsSource="{Binding myType}" AlternationCount="2" Style="{DynamicResource ListViewStyle1}">
<ListView.View>
<GridView>
<GridViewColumn Width="50" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Site1}" Width="80">
<GridViewColumnHeader Content="Site" Foreground="White" FontSize="15" FontWeight="SemiBold" HorizontalContentAlignment="Center"/>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Item1}" Width="150">
<GridViewColumnHeader Content="Item" Foreground="White" FontSize="15" FontWeight="SemiBold"/>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Proxy1}" Width="80">
<GridViewColumnHeader Content="Proxy" Foreground="White" FontSize="15" FontWeight="SemiBold"/>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Profile1}" Width="100">
<GridViewColumnHeader Content="Profile" Foreground="White" FontSize="15" FontWeight="SemiBold"/>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Dollars1}" Width="80">
<GridViewColumnHeader Content="Dollars" Foreground="White" FontSize="15" FontWeight="SemiBold"/>
</GridViewColumn>
<GridViewColumn Width="100">
<GridViewColumnHeader Content="Status" Foreground="White" FontSize="15" FontWeight="SemiBold"/>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Border x:Name="txtBorder" CornerRadius="5" Background="{Binding BackColor1}" Width="80" Height="27"
Padding="0,5,0,5">
<TextBlock Text="{Binding Status1, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
Foreground="White" HorizontalAlignment="Center" >
</TextBlock>
</Border>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="100">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Style="{DynamicResource ButtonIcon}"
hc:IconElement.Geometry="{StaticResource down}" Foreground="White" />
</DataTemplate>
</GridViewColumn.CellTemplate>
<GridViewColumnHeader Content="Action" Foreground="White" FontSize="15" FontWeight="SemiBold" HorizontalContentAlignment="Left"/>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
Please let me know where I'm doing a mistake
CodePudding user response:
You should loop through each element in code behind and set the waiting value. Then set the new value for each cell after the operation for that cell finished. Like BionicCode I do not get the problem exactly
CodePudding user response:
First, let your data model implement INotifyPropertyChanged
(Microsoft Docs example).
Then iterate over your source collection. You can use Task.Delay to force the loop to slow down (in times where users seek to have the fastest machine to make them wait less):
MainWindow.xaml
<Window>
<ListBox ItemsSource="{Binding ColoredItems}">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type local:ColoredItem}">
<TextBlock Text="{Binding Text}">
<TextBlock.Background>
<SolidColorBrush Color="{Binding Color}" />
</TextBlock.Background>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Window>
MainWindow.xaml.cs
Public Partial Class MainWindow
Inherits Window
Public ReadOnly Property ColoredItems As ObservableCollection(Of ColoredItem)
' The cancellation source, which must be disposed after use.
' You can only use it once.
Private Property CancellationTokenSource As CancellationTokenSource
Public Sub New(ByVal dataContext As TestViewModel)
InitializeComponent()
Me.DataContext = Me
Me.ColoredItems = New ObservableCollection(Of ColoredItem) From {
New ColoredItem("Waiting", Colors.Green),
New ColoredItem("Waiting", Colors.Green),
New ColoredItem("Waiting", Colors.Green),
New ColoredItem("Waiting", Colors.Green),
New ColoredItem("Waiting", Colors.Green),
New ColoredItem("Waiting", Colors.Green),
New ColoredItem("Waiting", Colors.Green)
}
End Sub
' Add CancellationToke parameter for cancellation support
Private Async Function ChangeItemsStateAsync(
ByVal state As String,
ByVal color As Color,
ByVal isDelayed As Boolean,
ByVal cancellationToken As CancellationToken) As Task
cancellationToken.ThrowIfCancellationRequested()
Dim randomGenerator = New Random()
Dim coloredItems As List(Of ColoredItem) = Me.ColoredItems.ToList()
While coloredItems.Any()
cancellationToken.ThrowIfCancellationRequested()
Dim randomIndex As Integer = randomGenerator.[Next](0, coloredItems.Count - 1)
Dim item As ColoredItem = coloredItems(randomIndex)
coloredItems.RemoveAt(randomIndex)
item.Text = state
item.Color = color
If isDelayed Then
Dim delayInMilliseconds As Integer = randomGenerator.[Next](125, 3000)
Await Task.Delay(delayInMilliseconds, cancellationToken)
End If
End While
End Function
' The Button.Click handler for the cancel button
Private Sub OnCancelButtonClicked(ByVal sender As Object, ByVal e As EventArgs)
Me.CancellationTokenSource?.Cancel()
End Sub
Private Async Sub OnClick(ByVal sender As Object, ByVal e As RoutedEventArgs)
Using Me.CancellationTokenSource AS CancellationTokenSource New CancellationTokenSource()
Try
Await ChangeItemsStateAsync("Searching", Colors.Orange, False, Me.CancellationTokenSource.Token)
Await ChangeItemsStateAsync("Delayed", Colors.Red, True, Me.CancellationTokenSource.Token)
Catch ex As OperationCanceledException
End Try
End Using
End Sub
End Class
ColoredItem.cs
Public Class ColoredItem
Inherits INotifyPropertyChanged
Public Sub New(ByVal text As String, ByVal color As Color)
Me.Color = color
Me.Text = text
End Sub
Private color As Color
Public Property Color As Color
Get
Return Me.color
End Get
Set(ByVal value As Color)
Me.color = value
OnPropertyChanged()
End Set
End Property
Private text As String
Public Property Text As String
Get
Return Me.text
End Get
Set(ByVal value As String)
Me.text = value
OnPropertyChanged()
End Set
End Property
End Class
After reviewing your code i found the following error that causes the ill behavior:
The posted code of your MainWindow
class looks incomplete. However, the partial constructor you have showed is the reason for your ill behaving code. You only create a single instance of Custom_Type
, named type1
. The collection contains the same instance multiple times (10 times). But it must be individual instances, of course. Make sure to move the assignment of type1
inside the loop.
Furthermore, you have added the line myType.Add(type1)
twice. Remove the one outside of the loop.
myType = New ObservableCollection(Of Custom_Type)()
For i = 0 To 10
Dim type1 = New Custom_Type("site.org", "Snow Globe - Coke Bottel", "Luminati", "[email protected]", "$1.22", "Waiting", New SolidColorBrush(Color.FromRgb(44, 184, 185)))
myType.Add(type1)
Next
listView.ItemsSource = myType