Wpf ItemTemplate中包含绑定组合框的ItemsControl
我刚刚遇到了一个问题,无法将ItemsControl中的集合与包含有界ComboBox的ItemTeplate绑定 在我的场景中,我需要为集合中的每个项目“生成”包含文本框和组合框的表单,并让用户更新项目。我可以使用DataGrid,但我希望在编辑模式下查看所有行,所以我使用带有自定义ItemTemplate的ItemsControl 可以编辑文本框,但当您尝试更改任何组合框时,其他行中的所有其他组合框也将更改。 它是一个bug还是一个特性 谢谢,昂德雷 Window.xamlWpf ItemTemplate中包含绑定组合框的ItemsControl,wpf,binding,combobox,Wpf,Binding,Combobox,我刚刚遇到了一个问题,无法将ItemsControl中的集合与包含有界ComboBox的ItemTeplate绑定 在我的场景中,我需要为集合中的每个项目“生成”包含文本框和组合框的表单,并让用户更新项目。我可以使用DataGrid,但我希望在编辑模式下查看所有行,所以我使用带有自定义ItemTemplate的ItemsControl 可以编辑文本框,但当您尝试更改任何组合框时,其他行中的所有其他组合框也将更改。 它是一个bug还是一个特性 谢谢,昂德雷 Window.xaml <Wind
<Window x:Class="ComboInItemsControlSample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="480" Width="640">
<Window.Resources>
<CollectionViewSource x:Key="cvsComboSource"
Source="{Binding Path=AvailableItemTypes}" />
<DataTemplate x:Key="ItemTemplate">
<Border BorderBrush="Black" BorderThickness="0.5" Margin="2">
<Grid Margin="3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="20" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" Text="{Binding Path=ItemValue}" />
<ComboBox Grid.Column="2"
SelectedValue="{Binding Path=ItemType}"
ItemsSource="{Binding Source={StaticResource cvsComboSource}}"
DisplayMemberPath="Name"
SelectedValuePath="Value" />
</Grid>
</Border>
</DataTemplate>
</Window.Resources>
<Grid>
<ItemsControl ItemsSource="{Binding Path=SampleItems}"
ItemTemplate="{StaticResource ItemTemplate}"
Margin="10" />
</Grid>
Window.xaml.cs
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
DataContext = new ViewModel();
}
}
public class ViewModel
{
public ViewModel()
{
SampleItems = new List<SampleItem> {
new SampleItem { ItemValue = "Value 1" },
new SampleItem { ItemValue = "Value 2" },
new SampleItem { ItemValue = "Value 3" }
};
AvailableItemTypes = new List<SampleItemType> {
new SampleItemType { Name = "Type 1", Value = 1 },
new SampleItemType { Name = "Type 2", Value = 2 },
new SampleItemType { Name = "Type 3", Value = 3 },
new SampleItemType { Name = "Type 4", Value = 4 }
};
}
public IList<SampleItem> SampleItems { get; private set; }
public IList<SampleItemType> AvailableItemTypes { get; private set; }
}
public class SampleItem : ObservableObject
{
private string _itemValue;
private int _itemType;
public string ItemValue
{
get { return _itemValue; }
set { _itemValue = value; RaisePropertyChanged("ItemValue"); }
}
public int ItemType
{
get { return _itemType; }
set { _itemType = value; RaisePropertyChanged("ItemType"); }
}
}
public class SampleItemType : ObservableObject
{
private string _name;
private int _value;
public string Name
{
get { return _name; }
set { _name = value; RaisePropertyChanged("Name"); }
}
public int Value
{
get { return _value; }
set { _value = value; RaisePropertyChanged("Value"); }
}
}
public abstract class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName) {
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
公共部分类窗口1:窗口
{
公共窗口1()
{
初始化组件();
DataContext=新的ViewModel();
}
}
公共类视图模型
{
公共视图模型()
{
SampleItems=新列表{
新的SampleItem{ItemValue=“Value 1”},
新的SampleItem{ItemValue=“Value 2”},
新建SampleItem{ItemValue=“Value 3”}
};
AvailableItemTypes=新列表{
新的SampleItemType{Name=“Type 1”,Value=1},
新的SampleItemType{Name=“Type 2”,Value=2},
新的SampleItemType{Name=“Type 3”,Value=3},
新的SampleItemType{Name=“Type 4”,Value=4}
};
}
公共IList样本项{get;private set;}
public IList AvailableItemTypes{get;private set;}
}
公共类示例项:ObserveObject
{
私有字符串_itemValue;
私有int_itemType;
公共字符串ItemValue
{
获取{return\u itemValue;}
设置{u itemValue=value;RaisePropertyChanged(“itemValue”);}
}
公共int ItemType
{
获取{return\u itemType;}
set{u itemType=value;RaisePropertyChanged(“itemType”);}
}
}
公共类SampleItemType:ObserveObject
{
私有字符串\u名称;
私有整数值;
公共字符串名
{
获取{return\u name;}
设置{u name=value;RaisePropertyChanged(“name”);}
}
公共整数值
{
获取{返回_值;}
设置{u value=value;RaisePropertyChanged(“value”);}
}
}
公共抽象类ObserveObject:INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
受保护的void RaisePropertyChanged(字符串propertyName){
var handler=PropertyChanged;
if(handler!=null)handler(这是新的PropertyChangedEventArgs(propertyName));
}
}
图片
虽然每行都有一个组合框,但它并不认为这些组合框是分开的。i、 它们都使用相同的集合和相同的selectedValue,因此当一个框中的值更改时,所有框中的值都会更改
解决此问题的最佳方法是将SampleItemType集合作为属性添加到SampleItem模型中,然后将组合框绑定到该属性。我认为这是因为您绑定到跟踪当前项的
CollectionViewSource
。请尝试直接绑定到您的列表,这样不会跟踪当前项目
<ComboBox Grid.Column="2"
SelectedValue="{Binding Path=ItemType}"
DisplayMemberPath="Name"
SelectedValuePath="Value"
ItemsSource="{Binding RelativeSource={
RelativeSource AncestorType={x:Type ItemsControl}},
Path=DataContext.AvailableItemTypes}" />
嗯,我是个白痴,你当然是对的:-)谢谢你睁开眼睛:-)。有时我看不到明显的东西。ItemsSource技巧+1。有没有办法让智能感知系统如此强大?@MikeCole,我不知道。您可能可以使用定制的标记扩展来做一些事情,但我认为这比尝试和构建要麻烦得多:)根据Rachel的回答,如果我设置ComboBox.IsSynchronizedWithCurrentItem=“false”,我的解决方案就会行得通