C# Usercontrol中具有CompositeCollection的WPF组合框不工作:SelectedIndex设置为-1

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代码

我正在使用MVVM

我有一个由

  • 内容为“选择供应商”的ComboboxItem
  • 有界的CollectionContainer
当我在视图中直接使用ComboBox XAML代码时,SelectedIndex设置为0(如预期的那样)

但是,当我将ComboBox XAML代码放入Usercontrol并在视图中使用该控件时,SelectedIndex设置为-1。 你知道如何解决这个问题,这样我就可以使用usercontrol了吗

我所有的装订都能用

注:

  • 当Combobox XAML代码直接显示在视图中时:当用户选择“选择供应商”时,ComboboxConverter将供应商属性设置为null
但是,当ComboBox XAML代码位于Usercontrol中时,代码不会进入

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代码可以工作?