C# Usercontrol中具有CompositeCollection的WPF组合框不工作:SelectedIndex设置为-1
我正在使用MVVM 我有一个由C# Usercontrol中具有CompositeCollection的WPF组合框不工作:SelectedIndex设置为-1,c#,wpf,xaml,combobox,user-controls,C#,Wpf,Xaml,Combobox,User Controls,我正在使用MVVM 我有一个由 内容为“选择供应商”的ComboboxItem 有界的CollectionContainer 当我在视图中直接使用ComboBox XAML代码时,SelectedIndex设置为0(如预期的那样) 但是,当我将ComboBox XAML代码放入Usercontrol并在视图中使用该控件时,SelectedIndex设置为-1。 你知道如何解决这个问题,这样我就可以使用usercontrol了吗 我所有的装订都能用 注: 当Combobox XAML代码
- 内容为“选择供应商”的ComboboxItem
- 有界的CollectionContainer
- 当Combobox XAML代码直接显示在视图中时:当用户选择“选择供应商”时,ComboboxConverter将供应商属性设置为null
if (comboboxItem.Content.ToString() == "Select a vendor")
{
//gets here when code is in view <-> code in control
return null;
}
if(comboboxItem.Content.ToString()=“选择供应商”)
{
//当代码在视图中时获取此控件中的代码
返回null;
}
ComboboxConverter
public class ComboboxConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var vendor = value as Vendor;
if (vendor != null)
{
return vendor;
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
var comboboxItem = value as ComboBoxItem;
if (comboboxItem != null)
{
if (comboboxItem.Content.ToString() == "Select a vendor")
{
//gets here when code is in view <-> code in control
return null;
}
return null;
}
var vendor = value as Vendor;
if (vendor != null)
{
return vendor;
}
return null;
}
}
公共类ComboboxConverter:IValueConverter
{
公共对象转换(对象值、类型targetType、对象参数、CultureInfo区域性)
{
var供应商=作为供应商的价值;
如果(供应商!=null)
{
退货供应商;
}
返回null;
}
公共对象转换回(对象值、类型targetType、对象参数、CultureInfo区域性)
{
var comboboxItem=作为comboboxItem的值;
if(comboboxItem!=null)
{
if(comboboxItem.Content.ToString()=“选择供应商”)
{
//当代码在视图中时获取此控件中的代码
返回null;
}
返回null;
}
var供应商=作为供应商的价值;
如果(供应商!=null)
{
退货供应商;
}
返回null;
}
}
供应商控制
<UserControl x:Class="Tool.Controls.VendorControl"
xmlns:local="clr-namespace:Tool.Controls"
xmlns:System="clr-namespace:System;assembly=mscorlib"
xmlns:objects='clr-namespace:Tool.Objects'
xmlns:converters='clr-namespace:Tool.Converters'
mc:Ignorable="d" >
<UserControl.Resources>
<converters:ComboboxConverter x:Key='ComboboxConverter' />
</UserControl.Resources>
<Grid>
<ComboBox Name='cmbVendor'
SelectedItem='{Binding Vendor, Converter={StaticResource ComboboxConverter}, Mode=TwoWay}'
Grid.Column='1'
IsSynchronizedWithCurrentItem='True'>
<ComboBox.Resources>
<CollectionViewSource x:Key='VendorsCollection'
Source='{Binding Vendors}' />
<DataTemplate DataType='{x:Type objects:Vendor}'>
<StackPanel Orientation='Horizontal'>
<TextBlock Text='{Binding Name}' />
</StackPanel>
</DataTemplate>
</ComboBox.Resources>
<ComboBox.ItemsSource>
<CompositeCollection>
<ComboBoxItem Content='Select a vendor' />
<CollectionContainer Collection='{Binding Source={StaticResource VendorsCollection}}' />
</CompositeCollection>
</ComboBox.ItemsSource>
</ComboBox>
private void OnWindowLoaded()
{
LoadVendors();
}
ObservableCollection<Vendor> _vendors = new ObservableCollection<Vendor>();
public ObservableCollection<Vendor> Vendors
{
get
{
return _vendors;
}
}
private Vendor _vendor;
public Vendor Vendor
{
get
{
return _vendor;
}
set
{
if (value != _vendor)
{
_vendor = value;
RaisePropertyChanged(nameof(Vendor));
}
}
}
private void LoadVendors()
{
var dVendors = VendorHelper.GetVendors();
if (Vendors.Count > 0)
{
DispatcherHelper.CheckBeginInvokeOnUI(() => Vendors.Clear());
}
dVendors.ForEach(dV =>
{
var vendor = new Vendor(dV);
DispatcherHelper.CheckBeginInvokeOnUI(() => Vendors.Add(vendor));
});
}
视图模型
<UserControl x:Class="Tool.Controls.VendorControl"
xmlns:local="clr-namespace:Tool.Controls"
xmlns:System="clr-namespace:System;assembly=mscorlib"
xmlns:objects='clr-namespace:Tool.Objects'
xmlns:converters='clr-namespace:Tool.Converters'
mc:Ignorable="d" >
<UserControl.Resources>
<converters:ComboboxConverter x:Key='ComboboxConverter' />
</UserControl.Resources>
<Grid>
<ComboBox Name='cmbVendor'
SelectedItem='{Binding Vendor, Converter={StaticResource ComboboxConverter}, Mode=TwoWay}'
Grid.Column='1'
IsSynchronizedWithCurrentItem='True'>
<ComboBox.Resources>
<CollectionViewSource x:Key='VendorsCollection'
Source='{Binding Vendors}' />
<DataTemplate DataType='{x:Type objects:Vendor}'>
<StackPanel Orientation='Horizontal'>
<TextBlock Text='{Binding Name}' />
</StackPanel>
</DataTemplate>
</ComboBox.Resources>
<ComboBox.ItemsSource>
<CompositeCollection>
<ComboBoxItem Content='Select a vendor' />
<CollectionContainer Collection='{Binding Source={StaticResource VendorsCollection}}' />
</CompositeCollection>
</ComboBox.ItemsSource>
</ComboBox>
private void OnWindowLoaded()
{
LoadVendors();
}
ObservableCollection<Vendor> _vendors = new ObservableCollection<Vendor>();
public ObservableCollection<Vendor> Vendors
{
get
{
return _vendors;
}
}
private Vendor _vendor;
public Vendor Vendor
{
get
{
return _vendor;
}
set
{
if (value != _vendor)
{
_vendor = value;
RaisePropertyChanged(nameof(Vendor));
}
}
}
private void LoadVendors()
{
var dVendors = VendorHelper.GetVendors();
if (Vendors.Count > 0)
{
DispatcherHelper.CheckBeginInvokeOnUI(() => Vendors.Clear());
}
dVendors.ForEach(dV =>
{
var vendor = new Vendor(dV);
DispatcherHelper.CheckBeginInvokeOnUI(() => Vendors.Add(vendor));
});
}
private void OnWindowLoaded()
{
LoadVendors();
}
ObservableCollection_供应商=新的ObservableCollection();
公开收集供应商
{
得到
{
退回供应商;
}
}
私人供应商(u供应商),;
公共供应商
{
得到
{
退回供应商;
}
设置
{
如果(值!=\u供应商)
{
_供应商=价值;
RaisePropertyChanged(供应商名称));
}
}
}
私有void LoadVendors()
{
var dVendors=VendorHelper.GetVendors();
如果(供应商数量>0)
{
DispatcherHelper.CheckBeginInvokeOnUI(()=>Vendors.Clear());
}
dVendors.ForEach(dV=>
{
var供应商=新供应商(dV);
DispatcherHelper.CheckBeginInvokeOnUI(()=>Vendors.Add(vendor));
});
}
开始时,当供应商为null时,函数Convert也将返回null,但您的组合框不知道null的含义,这就是为什么它将其所选索引值设置为-1。
您可以通过创建一个行为来解决此问题,该行为将在索引0设置为-1时始终选择索引0
public class SelectFirstItemBehavior : Behavior<ComboBox>
{
protected override void OnAttached()
{
AssociatedObject.SelectionChanged += AssociatedObject_SelectionChanged;
}
protected override void OnDetaching()
{
AssociatedObject.SelectionChanged -= AssociatedObject_SelectionChanged;
base.OnDetaching();
}
private void AssociatedObject_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var combobox = sender as ComboBox;
if (combobox != null && combobox.SelectedIndex == -1)
{
combobox.SelectedIndex = 0;
}
}
}
在您的组合框中:
<i:Interaction.Behaviors>
<SelectFirstItemBehavior/>
</i:Interaction.Behaviors>
您不需要调用供应商的RaisePropertyChanged属性,因为它是一个可观察的集合already@MartinCh谢谢你的评论谢谢!这解决了问题。也许您还可以给出一个答案,为什么在没有提供行为解决方案的情况下,直接在视图中使用XAML代码(而不是combobox的SelectedIndex=0)时,XAML代码可以工作?