Mengubah ComboBox menjadi AutoCompleteBox menggunakan WPF Toolkit

Aug 17 2020

Saya mengalami sedikit kesulitan untuk mencapai konversi dari ComboBox yang "kompleks" menjadi AutoCompleteBox yang sama rumitnya. Tujuan saya adalah untuk dapat memilih dan mengatur Item ShoppingCart menjadi seperti salah satu Item dari daftar. Berikut tiga langkah yang harus diambil untuk mereproduksi situasi saya (saya menggunakan Stylet dan metode INPC SetAndNotify ()) :

  1. Buat dua objek, satu hanya memiliki properti Name dan yang lainnya hanya memiliki objek lain sebagai properti

    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. menginisialisasi dan Mengisi ItemsList dan Shoppingcart di DataContext (karena kita menggunakan MVVM, ini adalah 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. Buat AutoCompleteBox, ComboBox, dan TextBlock kecil di dalam View untuk menguji semuanya:

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

Mengubah Mode Binding SelectedItem AutoCompleteBox ke TwoWay membuatnya mencetak " [ProjectName] .ItemModel " yang berarti (saya kira?) Itu mendapatkan ItemModels dan bukan string, tetapi saya tidak bisa membuatnya bekerja. Setiap bantuan akan dihargai, terima kasih dan jangan ragu untuk mengedit posting saya jika memungkinkan untuk membuatnya lebih kecil.

Jawaban

Saliom Aug 21 2020 at 21:07

Setelah banyak upaya, akhirnya saya menemukan pelakunya:

  • INPC tidak diterapkan ShoppingCartModel.Itemmeskipun ada PropertyChangedBasewarisan (baik menerapkan INPC atau menghapus PropertyChangedBasepekerjaan warisan)

    public class ShoppingCartModel : PropertyChangedBase
    {
        private ItemModel _item;
        public ItemModel Item
        {
            get => _item;
            set => SetAndNotify(ref _item, value);
        }
    }
    
  • AutoCompleteBox SelectedItemharus berjenis sama ItemsSource, dan memiliki TwoWayModeBinding

    <toolkit:AutoCompleteBox ItemsSource="{Binding ItemsList}"
                             ValueMemberPath="Name"
                             SelectedItem="{Binding Path=ShoppingCart.Item, Mode=TwoWay}" 
                             ItemTemplate="{StaticResource AutoCompleteBoxItemTemplate}"/>
    
  • Dan akhirnya ... yang paling misterius adalah ComboBox! Hanya dengan berada di sana itu mengacaukan AutoCompleteBoxdan saya tidak tahu mengapa, hanya dengan mengomentari seluruh ComboBox membuat semuanya bekerja. Jika Anda tahu mengapa ComboBox merusak pengikatan AutoCompleteBox, silakan membantu.

Ada masalah lain, ketika menggunakan AutoCompleteBox di dalam ListView, tetapi lebih baik membuat pertanyaan terpisah untuk masalah itu di sini