【问题标题】:How to show entered text as Combobox selected item when "IsEditable" is true in UWP ComboBox?当 UWP ComboBox 中的“IsEditable”为真时,如何将输入的文本显示为 Combobox 选定项?
【发布时间】:2019-12-17 15:35:08
【问题描述】:

我想创建一个 ComboBox + TextBox,为此我尝试在 ComboBox 中设置“IsEditable”为真。 我正在使用一组对象作为 ComboBox 的 ItemSource,它工作正常。但是当我输入任何文本时,它会显示这个错误。

错误:BindingExpression 路径错误:在“Windows.Foundation.IReference`1”上找不到“ComboBoxOption”属性。抛出异常:CBExample2.exe 中的“System.NullReferenceException”

我认为这个错误是因为当我在组合框中输入文本时,它会将它作为一个未转换回对象的字符串。

这是我的完整代码。

MainPage.xaml

<Page.Resources>
    <local:ComboBoxItemConvert x:Key="ComboBoxItemConvert" />
</Page.Resources>

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel>
        <ComboBox Name="ComboBox"
                  DisplayMemberPath="ComboBoxHumanReadableOption"
                  Header="ComboBox"
                  IsEditable="True"
                  IsTextSearchEnabled="True"
                  ItemsSource="{x:Bind ComboBoxOptions}"
                  SelectedItem="{x:Bind SelectedComboBoxOption, Mode=TwoWay, Converter={StaticResource ComboBoxItemConvert}}"
                  SelectedValuePath="ComboBoxOption" />
        <TextBlock Name="BoundTextblock" Text="{x:Bind SelectedComboBoxOption.ComboBoxHumanReadableOption, Mode=OneWay}" />
    </StackPanel>
</Grid>

背后的代码

public sealed partial class MainPage : Page, INotifyPropertyChanged
{

    private ObservableCollection<ComboBoxItem> ComboBoxOptions;
    public event PropertyChangedEventHandler PropertyChanged;
    public MainPage()
    {
        this.InitializeComponent();
        ComboBoxOptions = new ObservableCollection<ComboBoxItem>();
        ComboBoxOptionsManager.GetComboBoxList(ComboBoxOptions);
        SelectedComboBoxOption = ComboBoxOptions[0];
    }

    public class ComboBoxItem
    {
        public string ComboBoxOption { get; set; }
        public string ComboBoxHumanReadableOption { get; set; }
    }

    public class ComboBoxOptionsManager
    {
        public static void GetComboBoxList(ObservableCollection<ComboBoxItem> ComboBoxItems)
        {
            var allItems = getComboBoxItems();
            ComboBoxItems.Clear();
            allItems.ForEach(p => ComboBoxItems.Add(p));
        }

        private static List<ComboBoxItem> getComboBoxItems()
        {
            var items = new List<ComboBoxItem>();

            items.Add(new ComboBoxItem() { ComboBoxOption = "Option1", ComboBoxHumanReadableOption = "Option 1" });
            items.Add(new ComboBoxItem() { ComboBoxOption = "Option2", ComboBoxHumanReadableOption = "Option 2" });
            items.Add(new ComboBoxItem() { ComboBoxOption = "Option3", ComboBoxHumanReadableOption = "Option 3" });

            return items;
        }
    }

    ComboBoxItem _SelectedComboBoxOption ;
    public ComboBoxItem SelectedComboBoxOption
    {
        get
        {
            return _SelectedComboBoxOption;
        }
        set
        {
            if (_SelectedComboBoxOption != value)
            {
                _SelectedComboBoxOption = value;
                RaisePropertyChanged("SelectedComboBoxOption");
            }
        }
    }

    void RaisePropertyChanged(string prop)
    {
        if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(prop)); }
    }
}

还有转换器类

public class ComboBoxItemConvert : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        if (value.GetType().Equals(typeof(ComboBoxItem)))
        {
            return value;
        }
        return new ComboBoxItem() { ComboBoxOption = "new", ComboBoxHumanReadableOption = "new" }; 

    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        return value as MainPage.ComboBoxItem;
    }
}

我想要的是将输入的文本添加为​​组合框中的新选项,输入时应将其视为已选中。 请帮忙。在过去的 4 天里,我一直停留在这一点上。提前致谢。

【问题讨论】:

    标签: c# asp.net uwp combobox uwp-xaml


    【解决方案1】:

    错误原因是转换器没有考虑null的情况。

    请按照以下步骤操作:

    1. MainPage 中删除了ComboBoxItemComboBoxOptionsManager 类的定义,分别定义。

    2. 重写ComboBoxItem的Equal方法来处理后续的项目添加

    public class ComboBoxItem
    {
        public string ComboBoxOption { get; set; }
        public string ComboBoxHumanReadableOption { get; set; }
    
        public override bool Equals(object obj)
        {
            return obj is ComboBoxItem item &&
                   ComboBoxOption == item.ComboBoxOption;
        }
    }
    
    1. 修改ComboBoxItemConvert的结构,添加数据集
    public class ComboBoxItemConvert : IValueConverter
    {
        public ObservableCollection<ComboBoxItem> Options { get; set; }
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            if (value !=null && value.GetType().Equals(typeof(ComboBoxItem)))
            {
                return value;
            }
            var newItem = new ComboBoxItem() { ComboBoxOption = "new", ComboBoxHumanReadableOption = "new" };
            if(Options!=null && !Options.Contains(newItem))
            {
                Options.Add(newItem);
            }
            return newItem;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            return value as ComboBoxItem;
        }
    }
    

    用法

    <local:ComboBoxItemConvert x:Key="ComboBoxItemConvert" Options="{x:Bind ComboBoxOptions}" />
    

    当您输入不在默认数据集 (ComboBoxOptions) 中的项目并按 Enter 时,新的 ComboBoxItem 将作为选定项目添加到数据集中。


    如果您需要输入自定义文本并相应地生成新条目,则需要添加新内容。

    MainPage.xaml.cs

    private string _editText;
    public string EditText
    {
        get => _editText;
        set { _editText = value; RaisePropertyChanged("EditText"); }
    }
    

    转换器

    ...
    public string ComboBoxEditText { get; set; }
    ...
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        ...
        var newItem = new ComboBoxItem() { ComboBoxOption = ComboBoxEditText ?? "new", ComboBoxHumanReadableOption = ComboBoxEditText ?? "new" };
        if (Options != null && !Options.Contains(newItem))
        {
            Options.Add(newItem);
        }
        return newItem;
    }
    

    MainPage.xaml

    <Page.Resources>
        <local:ComboBoxItemConvert x:Key="ComboBoxItemConvert" Options="{x:Bind ComboBoxOptions}" ComboBoxEditText="{x:Bind EditText,Mode=OneWay}"/>
    </Page.Resources>
    
    ...
    <ComboBox Name="ComboBox"
          ...
          IsEditable="True"
          IsTextSearchEnabled="True"
          Text="{x:Bind EditText,Mode=TwoWay}"
          ...
          />
    ...
    
    

    这将满足您的要求。

    最好的问候。

    【讨论】:

    • 我进行了建议的更改,但它似乎不起作用。我注意到的唯一一次更改是,每当我第一次选择任何选项时,它都会被添加到列表中。任何建议将不胜感激。谢谢
    • 您好,您是否正确覆盖了ComboBoxItem.Equal 方法?另外,你能描述一下你的步骤吗?我无法在此处重现此问题
    • 我遵循的步骤:创建一个单独的类文件来创建 ComboBoxItemComboBoxOptionsManager 类。更新了ComboBoxItemConvert的代码。修改了MainPage.xaml 并根据您的建议进行编码。请您看一下我的代码并指导我哪里出错了。这是link to code
    • 您好,我检查了您的代码,请将您的Combo 中的SelectedValue 绑定替换为SelectedItemSelectedValue 指向您选择的数据模型的一个属性(项目中的ComboBoxOption,它是一个字符串),您的Converter 返回一个ComboBoxItem 类。类型不匹配导致转换问题
    • 嗨,也许这个case 可以帮助你。您可以创建一个ViewModel,然后将集合和变量放入其中。在 XAML 代码中,您可以将 ViewModel 绑定为 ListView 的 DataContext。在DataTemplate,可以使用{Binding ElementName=your_list_view, Path=DataContext.xxx}绑定数据。如果这与您的实际情况不符,请提出一个新问题,而不是跟进无关的问题
    猜你喜欢
    • 2010-12-23
    • 2018-07-30
    • 2020-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-15
    • 2020-10-18
    相关资源
    最近更新 更多