[英]ListView with ComboBox as item template don't update source when selection in ComboBox changes
我将ListView
绑定到ObservableCollection<string>
并且每个项目都应显示为ComboBox
。 问题是,当我更改ComboBox
选择时,它不会更新ObservableCollection<string>
。 这是xaml:
<ListView ItemsSource="{Binding CellValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Path=DataContext.Column.CellValueChoices, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView}}" SelectedIndex="0" IsEditable="True">
<i:Interaction.Behaviors>
<behaviors:CellFocusBehavior/>
<behaviors:FocusOnLoadBehavior/>
</i:Interaction.Behaviors>
<ComboBox.InputBindings>
<KeyBinding Command="{Binding Path=DataContext.ValidateAndInsertNewCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView}}" Key="Tab"/>
</ComboBox.InputBindings>
</ComboBox>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
ListView
DataContext
是CellViewModel
对象,包含ObservableCollection<string> CellValue
。
看着您的xaml,在我看来,您认为“ ItemsSource =” {Binding CellValue,Mode = TwoWay“是将wpf控件绑定到其对应的VM属性的方式,这不太正确。Itemsource绑定只能是一个就像ViewModel以单向方式将实现INotifyCollectionChanged的列表加载到GUI一样,将ItemsSource绑定到TwoWay并不能使GUI知道如何将DataTemplate内部的所有控件值更新回ViewModel。
相反,您应该将每个控件绑定到ViewModel属性的每个控件上,以实现此目的。 我给你做了一个样品。
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public class OrderViewModel : ViewModelBase
{
public ObservableCollection<string> ComboBoxOptions { get; set; }
private string orderId;
private string instrumentId;
private string selectedComboOption;
public OrderViewModel()
{
ComboBoxOptions = new ObservableCollection<string>
{
"Option1",
"Option2",
"Option3",
};
}
public string OrderId
{
get { return orderId; }
set
{
orderId = value;
OnPropertyChanged();
}
}
public string InstrumentId
{
get { return instrumentId; }
set
{
instrumentId = value;
OnPropertyChanged();
}
}
public string SelectedComboOption
{
get { return selectedComboOption; }
set
{
selectedComboOption = value;
OnPropertyChanged();
}
}
}
[Export]
public class MainViewModel : ViewModelBase
{
private OrderViewModel selectedOrder;
public ObservableCollection<OrderViewModel> Orders { get; set; }
public MainViewModel()
{
Orders = new ObservableCollection<OrderViewModel>
{
new OrderViewModel {OrderId = "Order1", InstrumentId = "Instrument1"},
new OrderViewModel {OrderId = "Order2", InstrumentId = "Instrument2"},
new OrderViewModel {OrderId = "Order2", InstrumentId = "Instrument3"}
};
}
public OrderViewModel SelectedOrder
{
get { return selectedOrder; }
set
{
selectedOrder = value;
OnPropertyChanged();
}
}
}
<Window x:Class="WpfTestProj.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfTestProj"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:MainViewModel, IsDesignTimeCreatable=False}"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListView ItemsSource="{Binding Orders}" SelectedItem="{Binding SelectedOrder}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding OrderId}" />
<TextBox Text="{Binding InstrumentId}" />
<ComboBox ItemsSource="{Binding ComboBoxOptions}"
SelectedItem="{Binding SelectedComboOption}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.