简体   繁体   中英

wpf combobox - performance after changing binding

I have two comboboxes. The items of both are enum values. Depending on selection in combo Foo there are different items available in combo Bar (binding change). The first time comboBar always pops up quickly - no matter wether comboFoo has popped up before or not. But after every selection change in comboFoo (after comboBar has popped up at least one time) comboBar pops up very slowly. I have not any idea how to fix it.

Enums

public enum Foo
{
    Foo1, Foo2, Foo3
}

public enum Bar
{
    Bar1, Bar2, Bar3, Bar4, Bar5, Bar6, Bar7, Bar8, Bar9, Bar10, 
    Bar11, Bar12, Bar13, Bar14, Bar15, Bar16, Bar17, Bar18,
}

Mark up for enums

public class EnumValuesExtension : MarkupExtension
{
    private readonly Type enumType;

    public EnumValuesExtension(Type enumType)
    {
        if (enumType == null)
            throw new ArgumentNullException("enumType");

        if (!enumType.IsEnum)
            throw new ArgumentException("Argument enumType must derive from type Enum.");

        this.enumType = enumType;
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return Enum.GetValues(enumType);
    }
}

Converter (usage see method below)

public class EnumToFilteredListConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (!(value is Type))
            return null;

        var enumType = (Type)value;

        if (!enumType.IsSubclassOf(typeof(Enum)))
            return null;

        Array allValues = Enum.GetValues(enumType);

        IEnumerable enumList;
        var filterList = (parameter == null) ? Enum.GetValues(enumType).Cast<Enum>() : (parameter as Array).Cast<Enum>();

        try
        {
            enumList = from Enum enumValue in allValues
                       where filterList.Contains(enumValue)
                       select enumValue;
        }
        catch (ArgumentNullException)
        {
            enumList = allValues;
        }
        catch (ArgumentException)
        {
            enumList = allValues;
        }
        return enumList;

    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

SelectionChanged method (code behind)

    private void cboFoo_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (comboBar == null)
            return;

        if (comboFoo.SelectedItem == null)
            return;

        var binding = new Binding
                          {
                              Source = typeof(Bar),
                              Converter = new EnumToFilteredListConverter()
                          };

        switch ((Foo)comboFoo.SelectedItem)
        {
            case Foo.Foo1: // Show only Bar1-Bar3
                binding.ConverterParameter = new Enum[] { Bar.Bar1, Bar.Bar2, Bar.Bar3 };
                break;
            case Foo.Foo2: // Show only Bar3-Bar5
                binding.ConverterParameter = new Enum[] { Bar.Bar3, Bar.Bar4, Bar.Bar5 };
                break;
            default: // Show all of Bar
                binding.ConverterParameter = null;
                break;
        }

        comboBar.SetBinding(ItemsControl.ItemsSourceProperty, binding);
    }

XAML

<StackPanel>            
    <ComboBox Name="comboFoo" ItemsSource="{Binding Source={markup:EnumValues {x:Type types:Foo}}}" SelectionChanged="cboFoo_SelectionChanged" />
    <ComboBox Name="comboBar" ItemsSource="{Binding Source={markup:EnumValues {x:Type types:Bar}}}" />
    <!--<ListBox Name="comboBar" ItemsSource="{Binding Source={markup:EnumValues {x:Type types:Bar}}}" />-->
</StackPanel>

If I use a listbox instead of comboBar I have not any performance problem, so I think the problem does not belong to the converter...

PS: VS2010, .NET4.0, Debug-Build and also Release-Build tested

Ok, the binding problem seems to be only on Windows Vista with .NET4 - probably a bug in combobox itself. The code above is fine.

I tested it with:

  • win8, .net 4.5, vs2012: no problem
  • win8, .net 4.0, vs2012: no problem
  • win7, .net 4.0, vs2010: no problem (on my colleague's computer)
  • vista, .net 4.0, vs2010: problem (on another colleague's computer and on my one)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM