gpt4 book ai didi

c# - ComboBox 的 SelectedItem 在实际值之前意外设置为 null

转载 作者:行者123 更新时间:2023-11-30 16:25:31 27 4
gpt4 key购买 nike

我有一个 ComboBox,它的 ItemsSource 绑定(bind)到一个新的(不是默认的)ListCollectionView,后者链接到一个 ObservableCollection。 ComboBox SelectedItem 属性绑定(bind)到公共(public) SelectedHat 属性。

第 1 步:选择 ComboBox 中的第 2 个项目。正如预期的那样,SelectedHat 现在是列表中的第二个帽子。第 2 步:(单击按钮)将列表中的第 2 个位置设置为一顶新帽子。 SelectedHat 首先设置为 null,然后设置为新的 Hat。

为什么在新Hat之前SelectedHat设置为null?

我希望能够 vm.Collection[index] = new Hat() 和
(1) 如果 ComboBox 选择了该索引,则保持选中状态而不是空白
(2) 只将 SelectedHat 设置一次给新的 Hat,而不是 null 然后再设置新的 Hat

C#:

public partial class MainWindow : Window
{
private readonly ViewModel vm;

public MainWindow()
{
InitializeComponent();
vm = new ViewModel();
DataContext = vm;
}

private void Button_Click(object sender, RoutedEventArgs e)
{
Hat item = new Hat { Name = "hat 2", Color = "Red"};
vm.Collection[1] = item;
}
}

public class ViewModel : BaseNotifyPropertyChanged
{
public ObservableCollection<Hat> Collection { get; set; }
public ListCollectionView View { get; set; }

private Hat selectedHat;
public Hat SelectedHat
{
get { return selectedHat; }
set
{
selectedHat = value;
Console.WriteLine(string.Format("SelectedHat set to [{0}]", value));
NotifyPropertyChanged("SelectedHat");
}
}

public ViewModel()
{
Collection = new ObservableCollection<Hat>()
{
new Hat { Name = "hat 1", Color = "Black" },
new Hat { Name = "hat 2", Color = "Black" },
new Hat { Name = "hat 3", Color = "Black" },
};

View = new ListCollectionView(Collection);
View.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
}
}

public class Hat
{
public string Name { get; set; }
public string Color { get; set; }

public override string ToString()
{
return string.Format("{0} ({1})", Name, Color);
}
}

public abstract class BaseNotifyPropertyChanged : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

protected virtual void NotifyPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

XAML:

<StackPanel>
<TextBlock Text="{Binding Path=SelectedHat, Mode=OneWay}" />
<ComboBox ItemsSource="{Binding Path=View}" SelectedItem="{Binding Path=SelectedHat, UpdateSourceTrigger=PropertyChanged}" />
<Button Content="click me" Click="Button_Click" />
</StackPanel>

最佳答案

这是 ObservableCollection.SetItem 的实现

protected override void SetItem(int index, T item)
{
this.CheckReentrancy();
T obj = this[index];
base.SetItem(index, item);
this.OnPropertyChanged("Item[]");
this.OnCollectionChanged(NotifyCollectionChangedAction.Replace, (object) obj, (object) item, index);
}

如您所见,它引发了 OnPropertyChanged("Item[]") 然后是 OnCollectionChanged(NotifyCollectionChangedAction.Replace, (object) obj, (object) item, index)。OnCollectionChanged 具有参数“oldItem”和“newItem”。我希望如果我们通过组合框实现跟踪代码,我们会看到旧项目被删除并替换为 null,然后新项目被插入,这就是为什么你会得到你所经历的行为(我也看到了).

我的解决方法不是替换项目,而是添加新项目,更改当前选择的项目,然后删除旧项目。

private void ButtonClick(object sender, System.Windows.RoutedEventArgs e)
{
Hat newHat = new Hat { Name = "hat 2", Color = "Red" };

var viewModel = (ViewModel)DataContext;

var oldHat = viewModel.Collection[1];

if (viewModel.SelectedHat == oldHat)
{
viewModel.Collection.Add(newHat);
viewModel.SelectedHat = newHat;
viewModel.Collection.Remove(oldHat);
}
else
{
viewModel.Collection[1] = newHat;
}
}

关于c# - ComboBox 的 SelectedItem 在实际值之前意外设置为 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9829969/

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