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

时间:2018-04-17 09:47:31

标签: wpf vb.net listbox

我需要一个带有String项的列表框,然后每行有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

2 个答案:

答案 0 :(得分:1)

将名称设置为“PListBox”,然后

    For Each listb As ListBoxItem In PListBox.Items

    Next

你可以循环通过它们。您还可以在每个行上设置“标记”以单独引用它们。

'tag =“Plistbox_item1”'

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

答案 1 :(得分:0)

非常感谢Andy(在问题的评论中)。 我现在让我的代码工作,并且能够随意更新按钮。

<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