我有一个ComboBox,其ItemsSource绑定到一个新的(非默认)ListCollectionView,它链接到一个ObservableCollection。 ComboBox SelectedItem属性绑定到公共SelectedHat属性。
步骤1:选择ComboBox中的第2项。如预期的那样,SelectedHat现在是列表中的第二个帽子。 步骤2 :(单击按钮)将列表中的第二个点设置为新帽子。 SelectedHat首先设置为null,然后设置为新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>
答案 0 :(得分:3)
这是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;
}
}
答案 1 :(得分:0)
直接更改项目。我刚试过它。 vm.Collection [1] .name =“hat 2”