การแปลง ComboBox เป็น AutoCompleteBox โดยใช้ WPF Toolkit

Aug 17 2020

ฉันมีปัญหาเล็กน้อยในการแปลง ComboBox ที่ "ซับซ้อน" ให้เป็น AutoCompleteBox ที่ซับซ้อนเท่ากัน เป้าหมายของฉันคือสามารถเลือกและตั้งค่ารายการของ ShoppingCart ให้เป็นเหมือนหนึ่งในรายการของรายการ ต่อไปนี้เป็นสามขั้นตอนในการสร้างสถานการณ์ของฉันซ้ำ(ฉันใช้ Stylet และเมธอด SetAndNotify () INPC) :

  1. สร้างออบเจ็กต์สองชิ้นโดยหนึ่งมีคุณสมบัติ Name เท่านั้นและอีกชิ้นหนึ่งมีอ็อบเจ็กต์อื่นเป็นคุณสมบัติเท่านั้น

    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. เริ่มต้นและเติมข้อมูลทั้ง ItemsList และ Shoppingcart ใน DataContext (เนื่องจากเราใช้ MVVM จึงเป็น 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. สร้าง AutoCompleteBox, ComboBox และ TextBlock ขนาดเล็กภายใน View เพื่อทดสอบทั้งหมด:

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

การเปลี่ยนโหมดการเชื่อมโยงของ SelectedItem ของ AutoCompleteBox เป็น TwoWay ทำให้พิมพ์ " [ProjectName] .ItemModel " ซึ่งหมายความว่า(ฉันเดา?)ได้รับ ItemModels ไม่ใช่สตริง แต่ดูเหมือนว่าฉันจะไม่สามารถใช้งานได้ ความช่วยเหลือใด ๆ จะได้รับการชื่นชมขอบคุณและอย่าลังเลที่จะแก้ไขโพสต์ของฉันหากเป็นไปได้ที่จะทำให้เล็กลง

คำตอบ

Saliom Aug 21 2020 at 21:07

หลังจากพยายามหลายครั้งในที่สุดฉันก็พบผู้ร้าย:

  • ไม่มีการนำ INPC มาใช้ShoppingCartModel.Itemแม้จะมีการPropertyChangedBaseสืบทอด(ไม่ว่าจะใช้ INPC หรือลบPropertyChangedBaseงานที่สืบทอด)

    public class ShoppingCartModel : PropertyChangedBase
    {
        private ItemModel _item;
        public ItemModel Item
        {
            get => _item;
            set => SetAndNotify(ref _item, value);
        }
    }
    
  • AutoCompleteBox SelectedItemต้องเป็นประเภทเดียวกันItemsSourceและมีTwoWayโหมดBinding

    <toolkit:AutoCompleteBox ItemsSource="{Binding ItemsList}"
                             ValueMemberPath="Name"
                             SelectedItem="{Binding Path=ShoppingCart.Item, Mode=TwoWay}" 
                             ItemTemplate="{StaticResource AutoCompleteBoxItemTemplate}"/>
    
  • และสุดท้าย ... สิ่งที่ลึกลับที่สุดคือ ComboBox! เพียงแค่อยู่ที่นั่นมันยุ่งกับAutoCompleteBoxและฉันก็ไม่รู้ว่าทำไมเพียงแค่แสดงความคิดเห็น ComboBox ทั้งหมดก็ทำให้มันใช้งานได้ทั้งหมด หากคุณรู้ว่าเหตุใด ComboBox จึงหยุดการผูกของ AutoCompleteBox โปรดช่วย

แม้ว่าจะมีปัญหาอื่นเมื่อใช้ AutoCompleteBox ใน ListView แต่ควรสร้างคำถามแยกต่างหากสำหรับปัญหานั้นที่นี่