列表框 - 如何正确枚举 WPF 列表框的内容?WPF-VB.Net



我需要一个带有字符串项的列表框,后跟每行 2 个按钮。这是我在这里的 WPF 列表框上浏览了一些答案和教程后开始工作的。

现在我想以编程方式修改某些行上按钮上的文本,但似乎无法访问它们。

我想如果我在PListbox.items中将每个项目枚举为ItemCollection,我可以访问它们,但是PListbox.items声称返回一个字符串,而不是我预期的ItemCollection。

这是我的列表框的 XAML 标记。

<Window x:Class="PrinterChooser"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:Gatekeeper2018"
    mc:Ignorable="d"
    Title="PrinterChooser" Height="450" Width="500" Background="#FF005A9E" Loaded="Window_Loaded">
<Window.Resources>
    <ControlTemplate x:Key="ButtonControlTemplate1" TargetType="{x:Type Button}">
        <Border x:Name="border" BorderBrush="#FF669CC5" BorderThickness="{TemplateBinding BorderThickness}" Background="#FF337BB1" SnapsToDevicePixels="True" Margin="5,5,0,0">
            <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </Border>
        <ControlTemplate.Triggers>
            <Trigger Property="IsDefaulted" Value="True">
                <Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
            </Trigger>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Background" TargetName="border" Value="#FFBEE6FD"/>
                <Setter Property="BorderBrush" TargetName="border" Value="#FF3C7FB1"/>
            </Trigger>
            <Trigger Property="IsPressed" Value="True">
                <Setter Property="Background" TargetName="border" Value="#FFC4E5F6"/>
                <Setter Property="BorderBrush" TargetName="border" Value="#FF2C628B"/>
            </Trigger>
            <Trigger Property="ToggleButton.IsChecked" Value="True">
                <Setter Property="Background" TargetName="border" Value="#FFBCDDEE"/>
                <Setter Property="BorderBrush" TargetName="border" Value="#FF245A83"/>
            </Trigger>
            <Trigger Property="IsEnabled" Value="False">
                <Setter Property="Background" TargetName="border" Value="#FFF4F4F4"/>
                <Setter Property="BorderBrush" TargetName="border" Value="#FFADB2B5"/>
                <Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="#FF838383"/>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
    <Style  TargetType="{x:Type ListBoxItem}">
        <Style.Triggers>
            <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                <Setter Property="Background" Value="#19f39611"></Setter>
            </Trigger>
            <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                <Setter Property="Background" Value="#19000000"></Setter>
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
<Grid>
    <ListBox x:Name="PListBox" HorizontalAlignment="Left" Height="Auto" Margin="0,0,0,0" VerticalAlignment="Top" Width="Auto" Background="#FF005A9E" Foreground="White" AlternationCount="2">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="100"/>
                        <ColumnDefinition Width="175"/>
                        <ColumnDefinition Width="175"/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Grid.Column="0" Text="{Binding}" />
                    <Button x:Name="SessionButton" Grid.Column="1" Click="Button_Click" Template="{DynamicResource ButtonControlTemplate1}" Foreground="White">Add Printer this session</Button>
                    <Button x:Name="AllocateButton" Grid.Column="2" Click="Button_Click" Template="{DynamicResource ButtonControlTemplate1}" Foreground="White">Add Printer always</Button>
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

还有我的测试代码来寻找按钮 -

    Public Sub DisplayList(ByVal pString As String)
    Dim dum As String
    Dim plist As New List(Of String)
    For Each printer As String In pString.Split(","c)
        If printer IsNot "" Then
            plist.Add(printer)
        End If
    Next
    PListBox.ItemsSource = plist
    For Each itemcol As ItemCollection In PListBox.Items
        dum = itemcol.GetType.ToString
        MsgBox(dum)
    Next
End Sub

PString 包含列表的字符串项列表(逗号分隔(此列表显示正确,我可以通过单击按钮很好地处理事件。但是我需要设置按钮的初始状态(我可以在单击时执行此操作,但不能通过枚举列表框的内容(

    Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
    If sender.Content.contains("always") Then
        If sender.Content.startswith("Add") Then
            sender.Content = "Do not always add printer"
            sender.Foreground = Brushes.Yellow
            'Datacontext contains PrinterName as a String
            HandleMap(sender.Datacontext.ToString, True)
        Else
            sender.Content = "Add Printer always"
            sender.Foreground = Brushes.White
            'Datacontext contains PrinterName as a String
            HandleMap(sender.Datacontext.ToString, False)
        End If
    Else
        If sender.Content.startswith("Add") Then
            sender.Content = "Remove Printer this session"
            sender.Foreground = Brushes.Yellow
        Else
            sender.Content = "Add Printer this Session"
            sender.Foreground = Brushes.White
        End If
    End If
End Sub

设置名称,如"PListBox",然后

    For Each listb As ListBoxItem In PListBox.Items
    Next

您还可以在每行上设置一个"标签"以单独引用它们。

'标签 = "Plistbox_item1"'

        If listb.Tag = "Plistbox_item1" Then
        'do something cool.
        End If

非常感谢安迪(在问题的评论中(。我现在的代码可以正常工作,并且可以随意更新按钮。

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WPF_ListBox_Test_mvvm"
    xmlns:VisualBasic="clr-namespace:Microsoft.VisualBasic;assembly=Microsoft.VisualBasic" xmlns:My="clr-namespace:WPF_ListBox_Test_mvvm.My" x:Class="MainWindow"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Window.Resources>
    <DataTemplate x:Key="ListBoxTemplate">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="100"/>
                <ColumnDefinition Width="175"/>
                <ColumnDefinition Width="175"/>
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Column="0" Text="{Binding Name}"/>
            <Button Grid.Column="1" Content="{Binding AllocatedButton}" Click="Button_Click_1"/>
            <Button Grid.Column="2" Content="{Binding SessionButton}" Click="Button_Click_1"/>
        </Grid>
    </DataTemplate>
</Window.Resources>
<Grid>
    <ListBox x:Name="myListBox" HorizontalAlignment="Left" Height="399" Margin="10,10,0,0" VerticalAlignment="Top" Width="466" ItemTemplate="{StaticResource ListBoxTemplate}">

    </ListBox>
    <Button Content="Fill" HorizontalAlignment="Left" Margin="657,364,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
    <Button Content="Alter" HorizontalAlignment="Left" Margin="657,326,0,0" VerticalAlignment="Top" Width="75" Click="Button_Alter"/>
</Grid>

后面的测试工具。

Imports System.Collections.ObjectModel
Imports System.ComponentModel
Imports System.Runtime.CompilerServices
Class MainWindow
Public PrinterItems As ObservableCollection(Of PrinterItem)
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
    PrinterItems = New ObservableCollection(Of PrinterItem)
    PrinterItems.Clear()
    myListBox.DataContext = PrinterItems
    myListBox.ItemsSource = PrinterItems
    PrinterItems.Add(New PrinterItem("A16", "Add this Session", "Add always"))
    PrinterItems.Add(New PrinterItem("A22", "Add this Session", "Add always"))
End Sub
Private Sub Button_Click_1(sender As Object, e As RoutedEventArgs)
    MsgBox(sender.ToString)
End Sub
Private Sub Button_Alter(sender As Object, e As RoutedEventArgs)
    For Each item As PrinterItem In PrinterItems
        If item.Name.Equals("A22") Then
            item.SessionButton = "Woot"
        End If
    Next
End Sub
End Class
Public Class PrinterItem
Implements INotifyPropertyChanged
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
Public _name As String
Public _session As String
Public _allocate As String
Public Sub New(ByVal n As String, sButton As String, aButton As String)
    _name = n
    _session = sButton
    _allocate = aButton
End Sub
Public Property Name As String
    Get
        Return _name
    End Get
    Set(value As String)
        _name = value
        NotifyPropertyChanged()
    End Set
End Property
Public Property SessionButton As String
    Get
        Return _session
    End Get
    Set(value As String)
        _session = value
        NotifyPropertyChanged()
    End Set
End Property
Public Property AllocatedButton As String
    Get
        Return _allocate
    End Get
    Set(value As String)
        _allocate = value
        NotifyPropertyChanged()
    End Set
End Property
Public Overrides Function ToString() As String
    Return _name
End Function
End Class

最新更新