Conversión de un ComboBox en un AutoCompleteBox usando el kit de herramientas de WPF

Aug 17 2020

Estoy teniendo algunos problemas para lograr la conversión de un ComboBox "complejo" en un AutoCompleteBox igualmente complejo. Mi objetivo es poder seleccionar y configurar un artículo de ShoppingCart para que sea como uno de los artículos de una lista. Estos son los tres pasos a seguir para reproducir mi situación (estoy usando Stylet y su método INPC SetAndNotify ()) :

  1. Cree dos objetos, uno que tenga solo una propiedad Name y el otro que solo tenga el otro objeto como propiedad

    public class ItemModel : PropertyChangedBase
    {
        private string _name;
        public string Name
        {
            get => _name;
            set => SetAndNotify(ref _name, value);
        }
    }
    
    public class ShoppingCartModel : PropertyChangedBase
    {
        public ItemModel Item { get; set; }
    }
    
  2. inicializar y poblar tanto ItemsList como Shoppingcart en DataContext (ya que estamos usando MVVM, es ViewModel)

    public ShoppingCartModel ShoppingCart { get; set; }
    public ObservableCollection<ItemModel> ItemsList { get; set; }
    
    public ShellViewModel()
    {
        ItemsList = new ObservableCollection<ItemModel>()
        {
            new ItemModel { Name = "T-shirt"},
            new ItemModel { Name = "Jean"},
            new ItemModel { Name = "Boots"},
            new ItemModel { Name = "Hat"},
            new ItemModel { Name = "Jacket"},
        };
    
        ShoppingCart = new ShoppingCartModel() { Item = new ItemModel() };
    }
    
  3. Cree AutoCompleteBox, ComboBox y un pequeño TextBlock dentro de la Vista para probarlo todo:

    <Window [...] xmlns:toolkit="clr-namespace:System.Windows.Controls;assembly=DotNetProjects.Input.Toolkit">
    
        <!-- Required Template to show the names of the Items in the ItemsList -->
        <Window.Resources>
            <DataTemplate x:Key="AutoCompleteBoxItemTemplate">
                <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Background="Transparent">
                    <Label Content="{Binding Name}"/>
                </StackPanel>
            </DataTemplate>
        </Window.Resources>
    
        <StackPanel>
            <!-- AutoCompleteBox: can see the items list but selecting doesn't change ShoppingCart.Item.Name -->
            <Label Content="AutoCompleteBox with ShoppingCart.Item.Name as SelectedItem:"/>
            <toolkit:AutoCompleteBox ItemsSource="{Binding ItemsList}"
                                     ValueMemberPath="Name"
                                     SelectedItem="{Binding Path=ShoppingCart.Item.Name}" 
                                     ItemTemplate="{StaticResource AutoCompleteBoxItemTemplate}"/>
    
            <!-- ComboBox: can see the items list and selecting changes ShoppingCart.Item.Name value -->
            <Label Content="ComboBox with ShoppingCart.Item.Name as SelectedValue:"/>
            <ComboBox ItemsSource="{Binding ItemsList}" 
                      DisplayMemberPath="Name"
                      SelectedValue="{Binding Path=ShoppingCart.Item.Name}"
                      SelectedValuePath="Name"
                      SelectedIndex="{Binding Path=ShoppingCart.Item}" />
    
            <!-- TextBox: Typing "Jean" or "Jacket" updates the ComboBox, but not the AutoCompleteBox -->
            <Label Content="Value of ShoppingCart.Item.Name:"/>
            <TextBox Text="{Binding Path=ShoppingCart.Item.Name}"/>
        </StackPanel>
    </window>
    

Cambiar el modo de enlace de SelectedItem de AutoCompleteBox a TwoWay hace que imprima " [ProjectName] .ItemModel " lo que significa (¿supongo?) Está obteniendo ItemModels y no cadenas, pero parece que no puedo hacer que funcione. Cualquier ayuda será apreciada, gracias y siéntete libre de editar mi publicación si es posible hacerla más pequeña.

Respuestas

Saliom Aug 21 2020 at 21:07

Después de muchos intentos, finalmente encontré a los culpables:

  • INPC no implementado a ShoppingCartModel.Itempesar de la PropertyChangedBaseherencia (ya sea implementando INPC o eliminando el PropertyChangedBasetrabajo de herencia)

    public class ShoppingCartModel : PropertyChangedBase
    {
        private ItemModel _item;
        public ItemModel Item
        {
            get => _item;
            set => SetAndNotify(ref _item, value);
        }
    }
    
  • AutoCompleteBox SelectedItemdebe ser del mismo tipo ItemsSourcey tener un TwoWaymodoBinding

    <toolkit:AutoCompleteBox ItemsSource="{Binding ItemsList}"
                             ValueMemberPath="Name"
                             SelectedItem="{Binding Path=ShoppingCart.Item, Mode=TwoWay}" 
                             ItemTemplate="{StaticResource AutoCompleteBoxItemTemplate}"/>
    
  • Y finalmente ... ¡el más misterioso es el ComboBox! Simplemente por estar allí se mete con el AutoCompleteBoxy no tengo idea de por qué, solo comentar todo el ComboBox hace que todo funcione. Si sabe por qué ComboBox rompe el enlace de AutoCompleteBox, no dude en ayudar.

Sin embargo, hay otro problema al usar un AutoCompleteBox dentro de un ListView, pero es mejor crear una pregunta separada para ese problema aquí