用户控件中带有CompositeCollection的WPF ComboBox不起作用:SelectedIndex设置为-1 [英] WPF ComboBox with CompositeCollection in Usercontrol does not work: SelectedIndex set to -1

查看:39
本文介绍了用户控件中带有CompositeCollection的WPF ComboBox不起作用:SelectedIndex设置为-1的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用MVVM.

我有一个由以下组成的CompositeCollection

I have a CompositeCollection consisting of

  • 带有选择供应商"作为内容的ComboboxItem
  • 有界的CollectionContainer

当我直接在视图中使用ComboBox XAML代码时,SelectedIndex设置为0(如预期).

When I use the ComboBox XAML code directly in my view the SelectedIndex is set to 0 (as expected).

但是,当我将ComboBox XAML代码放入Usercontrol并在我的视图中使用该控件时,SelectedIndex设置为-1.任何想法如何解决此问题,以便我可以使用usercontrol?

However, when I put the ComboBox XAML code in a Usercontrol and use the control in my view, the SelectedIndex is set to -1. Any idea how to fix this issue, so that I can use the usercontrol?

我所有的绑定都有效.

注意:

  • 直接查看Combobox XAML代码时:当用户选择了选择供应商"时,ComboboxConverter会将Vendor属性设置为null.

但是,当ComboBox XAML代码位于用户控件中时,该代码不会进入

However, when ComboBox XAML code is in a Usercontrol the code does not get in

if (comboboxItem.Content.ToString() == "Select a vendor")
                {
                    //gets here when code is in view <-> code in control
                    return null;
                }

组合框转换器

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;
    }
}

VendorControl

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

ViewModel

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));
            });
    }

推荐答案

在您的Vendor为null的开头,函数Convert也将返回null,但是您的组合框不知道null的含义,这就是为什么它设置其选定索引的原因值为-1.您可以通过创建一种行为来解决此问题,该行为将在将索引设置为-1时始终选择索引0.

At the beginning when your Vendor is null, function Convert will return null as well but your combobox does not know what null means, that's why it sets its selected index value to -1. You can solve this by creating a behavior which will always select index 0 when it is set to -1.

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;
        }
    }
}

然后在您的XAML部分:

And then in your XAML part:

   xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

...

在组合框内:

<i:Interaction.Behaviors>
    <SelectFirstItemBehavior/>
</i:Interaction.Behaviors>

这篇关于用户控件中带有CompositeCollection的WPF ComboBox不起作用:SelectedIndex设置为-1的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆