我正在使用 WPF,并且有一个列表框,我已在后面的代码中将其绑定到 ObservableCollection。 它显示在多个视图中,并且工作完美(添加/删除,并在视图之间保持同步),直到我尝试向列表项添加图标。 现在,当将项目添加到 ObservableCollection 时,它甚至不会一致地将项目添加到列表框中。 我试图更改的不仅仅是在列表框中显示项目的名称,当项目“监视”属性为 true 时,我希望它在名称旁边显示图像,并在监视属性为 false 时删除该图像。 这部分正在工作,图标出现并被正确删除。 为了使此图标正确显示,我通过添加 ListBox.ItemTemplate->DataTemplate 修改了我的 xaml,如下所示。
以前的 XAML:
<ListBox
Name="CameraTargetsListbox"
Style="{DynamicResource NeuronListBoxStyle}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
Margin="0,8,0,4"
Height="140"
ItemContainerStyle="{DynamicResource NeuronListBoxItem_CameraTargets}"/>
当前的 XAML:
<ListBox
Name="CameraTargetsListbox"
Style="{DynamicResource NeuronListBoxStyle}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
Margin="0,8,0,4"
Height="140"
ItemContainerStyle="{DynamicResource NeuronListBoxItem_CameraTargets}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<ContentPresenter
Content="{Binding MonitoringItemIcon, UpdateSourceTrigger=PropertyChanged}"
Margin="-4,0,10,0" />
<TextBlock Text="{Binding DisplayName, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
我应该注意,我添加了“UpdateSourceTrigger=PropertyChanged”以尝试解决问题,但没有什么区别。
然后在后面的代码中我链接了 ObservableCollection,这段代码没有任何改变:
public CameraTargetsControl()
{
InitializeComponent();
this.DataContext = this;
CameraTargetsListbox.ItemsSource = PropertyList;
...
由于某种原因,由于我更改了列表框以显示模板而不是允许其默认显示信息,因此列表框无法一致更新。 现在,当我添加一个项目时,有时它会显示在列表框中,有时则不会。 如果我查看另一个视图,它将显示添加的项目,但有时项目会添加为空白(例如,正确列出第一个项目,然后是空白项目(列表框中没有文本,只有空格),然后添加第三个项目。我一生都无法弄清楚为什么该列表在视图之间不再同步,甚至在当前视图中也没有更新我已经阅读了很多有关使用 IPropertyChanged 的内容,但我不明白为什么。我应该需要在这里实现这个,因为可观察集合应该处理这个问题,事实上,直到我尝试更新列表项模板为止,如果它完全损坏,我可以看到需要 PropertyChanged 通知,但它仍然有效。 ..有时。
感谢所有帮助。 这是我用来更新列表的代码,基本上每次添加/删除项目时都会收到一个新列表,该列表会根据 ObservableCollection(PropertyList)进行检查并处理更新。
_ = Dispatcher.BeginInvoke(() =>
{
List<int> addList = new();
List<int> deleteList = new();
List<(int, int)> updateList = new(); // index from incoming list, index from listbox
CameraTarget selectedTarget = null;
CameraTargetsListbox.SelectionChanged -= CameraTargetsListbox_SelectionChanged;
if (CameraTargetsListbox.SelectedIndex != -1) selectedTarget = (CameraTarget)CameraTargetsListbox.SelectedItem;
// Check for additions and deletions
foreach (var target in targetList)
{
bool found = false;
foreach (var listedTarget in PropertyList)
{
if (target.Class == CameraTarget.TargetClass.AIS)
{
if (listedTarget.MMSI == target.MMSI)
{
updateList.Add((targetList.IndexOf(target), PropertyList.IndexOf(listedTarget)));
found = true;
break;
}
}
else if (listedTarget.TargetIndex == target.TargetIndex)
{
updateList.Add((targetList.IndexOf(target), PropertyList.IndexOf(listedTarget)));
found = true;
break;
}
}
if (!found) { addList.Add(targetList.IndexOf(target)); }
}
// Check for deletions
foreach (var listedTarget in PropertyList)
{
bool found = false;
foreach (var target in targetList)
{
if (target.Class == CameraTarget.TargetClass.AIS)
{
if (listedTarget.MMSI == target.MMSI)
{
found = true;
break;
}
}
else if (listedTarget.TargetIndex == target.TargetIndex)
{
found = true;
break;
}
}
if (!found) deleteList.Add(PropertyList.IndexOf(listedTarget));
}
if (updateList.Count > 0)
{
foreach (var index in updateList)
{
if (index.Item2 == CameraTargetsListbox.SelectedIndex)
{
if (PropertyList[index.Item2].Monitoring && PropertyList[index.Item2].MonitoringItemIcon == null)
{
PropertyList.RemoveAt(index.Item2);
PropertyList.Insert(index.Item2, targetList[index.Item1]);
}
else PropertyList[index.Item2] = targetList[index.Item1];
CameraTargetsListbox.SelectedIndex = index.Item2;
RefreshSelectedInfo();
}
else if(PropertyList[index.Item2].Monitoring && PropertyList[index.Item2].MonitoringItemIcon == null)
{
PropertyList.RemoveAt(index.Item2);
PropertyList.Insert(index.Item2, targetList[index.Item1]);
}
// Capture name updates
else if (PropertyList[index.Item2].ToString() != targetList[index.Item1].ToString())
{
PropertyList.RemoveAt(index.Item2);
PropertyList.Insert(index.Item2, targetList[index.Item1]);
}
else PropertyList[index.Item2] = targetList[index.Item1];
}
}
if (deleteList.Count > 0)
{
foreach (int index in deleteList)
{
if (index == CameraTargetsListbox.SelectedIndex) DeleteSelectedTarget(null, null);
else PropertyList.RemoveAt(index);
}
}
if (addList.Count > 0)
{
foreach (int index in addList)
{
PropertyList.Add(targetList[index]);
}
}
CameraTargetsListbox.SelectionChanged += CameraTargetsListbox_SelectionChanged;
CheckPropertyList();
});
这是我第一次发布问题,所以请让我知道我还能提供什么:)
ObservableCollection 将在项目发生更改时发出通知。但是 item 中的属性也需要通知才能调用 ui 更新。 例如:也许您需要更改“DisplayName”属性通知。确保您的“PropertyList item”模型是“INotifyPropertyChanged”。 您可以了解有关“mvvm 模式”或“绑定声明概述”或“INotifyPropertyChanged 接口”的更多信息。