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