【问题标题】:WPFToolkit AutoCompleteBox not binding correctly inside ListViewWPFToolkit AutoCompleteBox 在 ListView 内未正确绑定
【发布时间】:2020-12-10 22:20:22
【问题描述】:

After struggling a bit to just get started with WPFToolkit's AutoCompleteBox control,我在尝试在 ListView 中使用 AutoCompleteBox 时遇到了另一个问题,它几乎可以完美绑定,但出于某种原因,我忽略了它并没有首先显示 @987654326 @ 而是尝试将对象转换为提供 Namespace.object 而不是正确的 ValueMemberPath 值的字符串,但是当在 AutoCompleteBox 中选择另一个项目时,它可以正常工作,并且不会显示任何其他 Namespace.object

这是我的代码,您可以复制并粘贴它以获得相同的结果(不要忘记在 NuGet 包管理器中添加DotNetProjects.WpfToolkit.Input

  • 命名空间.MainWindow.xaml
<Window x:Class="Namespace.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Namespace"
        mc:Ignorable="d"
        xmlns:toolkit="clr-namespace:System.Windows.Controls;assembly=DotNetProjects.Input.Toolkit"
        Title="AutoCompleteBox in ListView" Height="300" Width="350" WindowStartupLocation="CenterScreen">
    
    <!-- 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 Margin="5">
        <StackPanel Orientation="Horizontal" Margin="0 5 0 0">
            <StackPanel Width="{Binding ElementName=FirstColumnWidth, Path=ActualWidth}">
                <TextBlock Text="ACB binded to Cart.Item"/>
                
                <!-- ACB that binds correctly -->
                <toolkit:AutoCompleteBox 
                                  ItemsSource="{Binding Path=ItemsList}"
                                   ValueMemberPath="Name"
                                   SelectedItem="{Binding Path=Cart.Item, Mode=TwoWay}"
                                   ItemTemplate="{StaticResource AutoCompleteBoxItemTemplate}"/>
            </StackPanel>

            <StackPanel Margin="15 0 0 0">
                <TextBlock Text="Value of Cart.Item.Name"/>
                <TextBlock Text="{Binding Path=Cart.Item.Name}"/>
            </StackPanel>
        </StackPanel>

        <TextBlock Margin="0 30 0 0" HorizontalAlignment="Center" Text="ListView with CartsList as ItemsListSource"/>
        <ListView ItemsSource="{Binding CartsList}">
            <ListView.View>
                <GridView>
                    <GridViewColumn x:Name="FirstColumnWidth">
                        <GridViewColumn.Header>
                            <TextBlock Text="ACB binded to each Cart.Item"/>
                        </GridViewColumn.Header>
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <!-- ACB that doesn't bind correctly -->
                                <toolkit:AutoCompleteBox
                                  ItemsSource="{
                                        Binding RelativeSource={RelativeSource AncestorType=Window},
                                        Path=DataContext.ItemsList}"
                                   ValueMemberPath="Name"
                                   SelectedItem="{Binding Path=Item, Mode=TwoWay}"
                                   ItemTemplate="{StaticResource AutoCompleteBoxItemTemplate}"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>

                    <GridViewColumn >
                        <GridViewColumn.Header>
                            <TextBlock Text="Value of each Cart.Item.Name"/>
                        </GridViewColumn.Header>
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Path=Item.Name}"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>
    </StackPanel>
</Window>
  • 代码隐藏 (MainWindow.xaml.cs)
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;

namespace Namespace
{
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        // INPC Implementation
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        // The list that contains Items that will be chosen in a Cart
        private ObservableCollection<Item> _ItemsList;
        public ObservableCollection<Item> ItemsList
        {
            get => _ItemsList;
            set
            {
                _ItemsList = value;
                OnPropertyChanged();
            }
        }

        // The list that contains Carts that will be shown in the ListView
        private ObservableCollection<Cart> _CartsList;
        public ObservableCollection<Cart> CartsList
        {
            get => _CartsList;
            set
            {
                _CartsList = value;
                OnPropertyChanged();
            }
        }

        // A signle Cart
        private Cart _Cart;
        public Cart Cart
        {
            get => _Cart;
            set
            {
                _Cart = value;
                OnPropertyChanged();
            }
        }

        public MainWindow()
        {
            DataContext = this;
            InitializeComponent();

            // Populating ItemsList
            ItemsList = new ObservableCollection<Item>()
            {
                new Item("T-shirt"), new Item("Jeans"), new Item("Boots"),
            };

            // Populating CartsList
            CartsList = new ObservableCollection<Cart>()
            {
                new Cart(ItemsList[0]),
                new Cart(ItemsList[2]),
                new Cart(ItemsList[1]),
                new Cart(ItemsList[0]),
                new Cart(ItemsList[1]),
            };

            // Setting an Item to Cart
            Cart = new Cart(ItemsList[2]);

        }
    }

    // Cart Object
    public class Cart
    {
        public Item Item { get; set; }

        public Cart(Item item) => Item = item;
    }

    // Item Object
    public class Item
    {
        // Important to be private set so it cannot be changed
        public string Name { get; private set; }

        public Item(string name) => Name = name;
    }
}

【问题讨论】:

    标签: c# wpf xaml data-binding wpftoolkit


    【解决方案1】:

    由于某种原因,在ListView 中嵌套AutoCompleteBox 时,不会触发根据ValueMemberPath 更新文本的选择更改。 SelectionChanged 事件甚至不会触发。我无法弄清楚为什么以及这是否是一个错误。不过,我可以向您展示一个使用Microsoft.Xaml.Behaviors.Wpf 包的解决方法

    您可以创建一个触发器操作来重置SelectedItem 并在AutoCompleteBox 上再次分配它。

    public class ForceUpdateSelectedItemAction : TriggerAction<AutoCompleteBox>
    {
       protected override void Invoke(object parameter)
       {
          var selectedItem = AssociatedObject.SelectedItem;
          AssociatedObject.SetCurrentValue(AutoCompleteBox.SelectedItemProperty, null);
          AssociatedObject.SetCurrentValue(AutoCompleteBox.SelectedItemProperty, selectedItem);
       }
    }
    

    此触发操作可用于AutoCompleteBoxLoaded 事件。

    <toolkit:AutoCompleteBox ...>
       <b:Interaction.Triggers>
          <b:EventTrigger EventName="Loaded">
             <local:ForceUpdateSelectedItemAction/>
          </b:EventTrigger>
       </b:Interaction.Triggers>
    </toolkit:AutoCompleteBox>
    

    这将导致在不更改绑定属性的情况下更新选择和文本。

    【讨论】:

    • 它成功了!我不确定这是否是一个错误,但现在一切都清楚了,多亏了你。我在 fork 的 github 页面上创建了一个新问题来在这里报告错误:github.com/dotnetprojects/WpfToolkit/issues/46
    猜你喜欢
    • 1970-01-01
    • 2013-06-14
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多