gpt4 book ai didi

c# - MVVM:在跟踪 IsSynchronizedWithCurrentItem 时绑定(bind)到列表 IsSelected

转载 作者:行者123 更新时间:2023-11-30 15:50:06 35 4
gpt4 key购买 nike

我通过绑定(bind)到 IsSelected 来跟踪 MVVM 设计中的 ListView 选择更改。我还需要通过启用 IsSynchronizedWithCurrentItem 来跟踪当前项目。

我发现当我有两个 ListView 绑定(bind)到同一个集合时,我得到了 InvalidOperationException:“Collection was modified; enumeration operation may not execute.”似乎是两个 ListView 之间的同步错误;一个正在触发 PropertyChanged 事件,而另一个可能正在更新选择器?

除了放弃使用 IsSynchronizedWithCurrentItem 并自己管理它之外,我想不出如何解决这个问题。有什么想法吗?

谢谢。

ViewModel 和背后的代码:

public class Item : INotifyPropertyChanged
{
public string Name{ get; set; }

public bool IsSelected
{
get { return isSelected; }
set { isSelected = value; OnPropertyChanged("IsSelected"); }
}
private bool isSelected;

public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

public class ViewModel
{
public ViewModel()
{
Items = new ObservableCollection<Item>()
{
new Item(){Name = "Foo"},
new Item(){Name = "Bar"}
};
}
public ObservableCollection<Item> Items { get; private set; }
}

public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
DataContext = new ViewModel();
}
}

XAML:

<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="100" Width="100">
<StackPanel>
<ListView DataContext="{Binding Items}" ItemsSource="{Binding}"
IsSynchronizedWithCurrentItem="True" SelectionMode="Single">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name, Mode=OneWay}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ListView DataContext="{Binding Items}" ItemsSource="{Binding}"
IsSynchronizedWithCurrentItem="True" SelectionMode="Single">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name, Mode=OneWay}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</Window>

最佳答案

我无法直接解决您的问题。不过,我确实有一个可行的解决方案。

您可以做的是在您的 View 模型中引入第二个名为“SelectedItem”的属性,该属性将包含对在您的 ListView 中选择的项目的引用。此外,在您的 View 模型中,您会监听 PropertyChanged 事件。如果关联的属性名称是 IsSelected,则将 SelectedItem 属性更新为该事件的发送者(现在 IsSelected = true 的 Item)。然后,您可以将 ListView 的 SelectedItem 属性绑定(bind)到 ViewModel 类的同名属性。

我修改后的 ViewModel 类的代码如下。

public class ViewModel : INotifyPropertyChanged
{
private Item _selectedItem;

public ViewModel()
{
Items = new ObservableCollection<Item>()
{
new Item {Name = "Foo"},
new Item {Name = "Bar"}
};

foreach ( Item anItem in Items )
{
anItem.PropertyChanged += OnItemIsSelectedChanged;
}
}

public ObservableCollection<Item> Items { get; private set; }

public Item SelectedItem
{
get { return _selectedItem; }
set
{
// only update if the value is difference, don't
// want to send false positives
if ( _selectedItem == value )
{
return;
}

_selectedItem = value;
OnPropertyChanged("SelectedItem");
}
}

public event PropertyChangedEventHandler PropertyChanged;

protected void OnItemIsSelectedChanged(object sender, PropertyChangedEventArgs e)
{
if ( e.PropertyName != "IsSelected" )
{
return;
}

SelectedItem = sender as Item;
}

private void OnPropertyChanged(string propertyName)
{
if ( PropertyChanged != null )
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}

关于c# - MVVM:在跟踪 IsSynchronizedWithCurrentItem 时绑定(bind)到列表 IsSelected,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/985868/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com