Home > Software design >  How to change a whole column value in ListView in WPF (C# or VB)
How to change a whole column value in ListView in WPF (C# or VB)

Time:05-23

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