将Tuple中bool值绑定到ListBox模板CheckBox致程序崩溃
问题根源与解决方案
你的问题核心出在Tuple的不可变性上!Tuple的Item2和Item3是只读属性(只有get访问器,没有set),而WPF中CheckBox.IsChecked的绑定默认是双向绑定(Mode=TwoWay)。当用户点击CheckBox时,WPF会尝试修改绑定的属性值,但Tuple的Item无法被修改,直接抛出异常导致程序崩溃。
解决步骤:
1. 创建自定义的用户选择ViewModel类
替换不可变的Tuple,用一个实现INotifyPropertyChanged的类来承载数据,这样既支持属性修改,又能通知UI更新:
public class UserSelectionViewModel : INotifyPropertyChanged { private UserDetails _userDetails; private bool _isWriteSelected; private bool _isManageSelected; public UserDetails UserDetails { get => _userDetails; set { _userDetails = value; OnPropertyChanged(nameof(UserDetails)); } } public bool IsWriteSelected { get => _isWriteSelected; set { _isWriteSelected = value; OnPropertyChanged(nameof(IsWriteSelected)); } } public bool IsManageSelected { get => _isManageSelected; set { _isManageSelected = value; OnPropertyChanged(nameof(IsManageSelected)); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
2. 更新你的集合类型与数据加载逻辑
把原来的ObservableCollection<Tuple<UserDetails, bool, bool>>换成自定义类的集合,并修改GetUsers方法:
private ObservableCollection<UserSelectionViewModel> _users; public ObservableCollection<UserSelectionViewModel> Users { get { return _users; } set { _users = value; OnPropertyRaised("Users"); } } public async Task GetUsers() { var tmp = await watchlistHelper.GetUsersAsync(); if (tmp != null) { Users = new ObservableCollection<UserSelectionViewModel>(); foreach (UserDetails details in tmp.Content) { Users.Add(new UserSelectionViewModel { UserDetails = details, IsWriteSelected = false, IsManageSelected = false }); } } }
3. 修改XAML绑定路径
现在绑定到自定义类的属性,而不是Tuple的Item:
<ListBox Grid.Column="2" Grid.Row="1" ItemsSource="{Binding Users, ElementName=uc}" HorizontalContentAlignment="Stretch" SelectionMode="Multiple"> <ListBox.ItemTemplate > <DataTemplate> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition SharedSizeGroup="write"/> <ColumnDefinition SharedSizeGroup="manage"/> </Grid.ColumnDefinitions> <TextBlock Margin="2" Text="{Binding UserDetails.UserName}" VerticalAlignment="Center"/> <CheckBox Margin="2" IsChecked="{Binding IsWriteSelected}" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="1"/> <CheckBox Margin="2" IsChecked="{Binding IsManageSelected}" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="2"/> </Grid> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
为什么这样能解决问题?
自定义类的属性有完整的get和set访问器,并且实现了INotifyPropertyChanged,既支持双向绑定的修改操作,又能在属性值变化时通知UI更新,完美适配WPF的数据绑定机制。
内容的提问来源于stack exchange,提问作者Simas Paškauskas
相关产品推荐
相关产品推荐

