我使用两个ListBox元素 . 一个是父(BucketListBox),它决定了应该在子节目中显示的内容 . Child(ObjectListBox)处于多选模式 . 一旦我选择了子元素中的特定元素,我转移到另一个父元素,子元素ListBox将更新为新的选择 .
当用户切换回先前浏览过的父母时,他应该能够看到他当时选择的孩子中的旧选择 . 我正在维护用户在孩子中选择的项目列表 . 我想使用此列表来更改他之前选择的元素的背景颜色 .
截至目前,这些元素仍处于选中状态,但未在UI中显示 .
这是我父母的XAML代码:
<ListBox Grid.Row="1" x:Name="BucketListBox" HorizontalContentAlignment="Stretch" SelectionChanged="BucketListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="10,10,10,10">
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<RelativePanel Grid.Row="0">
<TextBlock x:Name="BucketNameLabel" x:Uid="NameLabel"/>
<TextBlock Grid.Row="0" x:Name="BucketNameTextBlock" RelativePanel.AlignBottomWith="BucketNameLabel" RelativePanel.RightOf="BucketNameLabel" Text="{Binding BucketName}" Margin="10,10,10,10"/>
</RelativePanel>
<RelativePanel Grid.Row="1">
<TextBlock x:Name="BucketCreationDateLabel" FontSize="12" x:Uid="CreationDateLabel" HorizontalAlignment="Right"/>
<TextBlock x:Name="BucketCreationDateTextBlock" FontSize="12" RelativePanel.RightOf="BucketCreationDateLabel" RelativePanel.AlignBottomWith="BucketCreationDateLabel" Text="{Binding BucketCreationDate}" Margin="10,10,10,10" HorizontalAlignment="Right" />
</RelativePanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
子ListBox的代码:
<ListBox Grid.Row="1" Grid.Column="1" x:Name="ObjectListBox" HorizontalContentAlignment="Stretch" SelectionMode="Multiple">
<ListBox.ItemTemplate >
<DataTemplate >
<Grid Margin="10,10,10,10">
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<RelativePanel Grid.Row="0">
<TextBlock x:Name="NameLabel" x:Uid="NameLabel" Margin="10,10,10,10" />
<TextBlock x:Name="ObjectNameTextBlock" Text="{Binding ObjectName}" RelativePanel.RightOf="NameLabel" RelativePanel.AlignBottomWith="NameLabel" Margin="10,10,10,10" />
</RelativePanel>
<RelativePanel Grid.Row="1">
<TextBlock x:Name="SizeLabel" FontSize="12" x:Uid="SizeLabel"/>
<TextBlock x:Name="ObjectSize" FontSize="12" Margin="10,10,10,10" Text="{Binding Path=ObjectSize}" RelativePanel.RightOf="SizeLabel" RelativePanel.AlignBottomWith="SizeLabel"/>
</RelativePanel>
<RelativePanel Grid.Row="2">
<TextBlock x:Name="ObjectModificationDateLabel" FontSize="12" x:Uid="ModificationDateLabel" Margin="10,10,10,10" HorizontalAlignment="Right"/>
<TextBlock x:Name="ObjectModificationDateTextBlock" FontSize="12" Text="{Binding ObjectLastModificationDate}" Margin="10,10,10,10" RelativePanel.RightOf="ObjectModificationDateLabel" RelativePanel.AlignBottomWith="ObjectModificationDateLabel" HorizontalAlignment="Right"/>
</RelativePanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
这里是更新ListBoxItem的代码:(每当用户点击父ListBox中的新项时调用)
private void UpdateListBoxWithSelectedItems()
{
List<S3ObjectInfoHolder> currentList = (List<S3ObjectInfoHolder>)ObjectListBox.ItemsSource; //Getting the total elements being displayed in the current child list box
foreach (S3ObjectInfoHolder entry in listOfObjectsToTransfer) //listOfObjectsToTransfer is the list of all the entries from all the parents selected so far. So the intersection of currentList with this list gives the ones that are to be colored on UI so as the user knows the items are still selected
{
for (int i = 0; i < currentList.Count(); i++)
{
if (currentList[i].ObjectName.Equals(entry.ObjectName))
{
ObjectListBox.SelectedItems.Add(entry);
Debug.WriteLine("Selected Item:" + entry.ObjectName);
}
}
}
List<object> selectedItem = ObjectListBox.SelectedItems.ToList();
foreach (object item in selectedItem)
{
ListBoxItem selectedListBoxItem = ObjectListBox.ItemContainerGenerator.ContainerFromItem((S3ObjectInfoHolder)item) as ListBoxItem;
if(selectedListBoxItem!=null) selectedListBoxItem.Background = new SolidColorBrush(Colors.Turquoise);
}
}
selectedListBoxItem!=null 失败,并跳过该行 . 最后,这是绑定类的代码:
class S3ObjectInfoHolder
{
private string key;
private string bucketName;
private long size;
private string isObjectAFolder;
private string objectLastModificationDate;
public S3ObjectInfoHolder(string key, string bucketName)
{
this.key = key;
this.bucketName = bucketName;
isObjectAFolder = isObjectAFolderOrAFile(key);
}
private string isObjectAFolderOrAFile(string key)
{
if (key[key.Length - 1] == '/')
{
return "is a Folder";
}
else
{
return "is a File";
}
}
public string ObjectName
{
get
{
return key;
}
set
{
key = value;
}
}
public long ObjectSize
{
get
{
return size;
}
set
{
size = value;
}
}
public string ObjectIsFolder
{
get
{
return isObjectAFolder;
}
set
{
isObjectAFolder = value;
}
}
public string BucketName
{
get
{
return bucketName;
}
set
{
bucketName = value;
}
}
public string ObjectLastModificationDate
{
get
{
return objectLastModificationDate;
}
set
{
objectLastModificationDate = value;
}
}
}
1 回答
S3ObjectInfoHolder
需要实现INotifyPropertyChanged .S3ObjectInfoHolder
ListBox
中,当前不可见的任何ListBoxItem
将被重用于另一个数据项 . 这叫做"virtualization";它减少了创建的控件数量 .因此,当用户滚动此内容时,当具有彩色背景的项目滚动到视图外时,实际的
ListBoxItem
控件将重新用于滚动到视图中的下一个项目 . 它仍将具有相同的背景颜色 . 这是正确的吗?通常不会,并且没有任何事件可以让您介入并更正它 . 根本没有活动 . 那是因为你应该使用数据绑定而不是直接搞乱控件 .你为自己买了一个可怕的蠕虫病毒试图在代码隐藏中做到这一点 . 这比你知道的还要糟糕 . 但是我向你展示的数据绑定方法更加防错,所以一切都很好 .
您应该有一个主视图模型,而不是在代码隐藏中执行此操作;我劝你研究一下 .
所有的viewmodel实际上都是一个继承自我给你的
NotificationBase
的类,或者来自其他一些基类的类 . 视图模型的属性在更改时会引发通知,并且对于可能在将其用作ItemsSource
时添加或删除项目的任何集合,它使用ObservableCollection<T>
而不是List<T>
.S3ObjectInfoHolder
,随着我的更改,开始成为一个视图模型 . 它's not the main viewmodel. It'是一个儿童视图模型 . 您应该将RaisePropertyChanged
调用添加到它拥有的每个属性 . 当您这样做,并且在XAML中使用带有该属性的Binding
时,将在属性值更改时通知Binding
,并且UI将自动更新 .但就目前而言,我只会告诉你如何修改你所拥有的东西 .
我不知道你为什么要比较名字 . 也许
currentList[i]
和entry
是相同的实际对象;我无法猜测 .并用容器的东西摆脱第二个循环 .