UWP Combobox绑定到SelectedItem属性

15

我正在尝试使用绑定使下拉框(combobox)工作,以便最终将其用于一些设置。我可以从可观察集合中填充项目并将“SelectedItem”绑定到属性SelectedItem="{x:Bind SelectedComboBoxOption}"

但是,当我更改选择时,文本框中绑定到此属性的内容未反映出来。在代码后台中,它在启动时设置属性一次,但在更改下拉框中的项目时不会设置。我可能漏了什么,但我不清楚。有什么想法吗?

这是XAML:

<Page
x:Class="ComboBoxTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ComboBoxTest"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

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

这是代码的背后:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;



namespace ComboBoxTest
{

 public sealed partial class MainPage : Page, INotifyPropertyChanged
 {

    private ObservableCollection<ComboBoxItem> ComboBoxOptions;

    public MainPage()
    {
        this.InitializeComponent();
        ComboBoxOptions = new ObservableCollection<ComboBoxItem>();
        ComboBoxOptionsManager.GetComboBoxList(ComboBoxOptions);
    }

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


    string _SelectedComboBoxOption = "Option1";
    public string 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 event PropertyChangedEventHandler PropertyChanged;
 }
}
3个回答

13

正如 @Mike Eason 和 @kubakista 所说,您需要明确设置 Mode。但这不会完全解决您的问题。

在您的代码中,SelectedComboBoxOption 是一个字符串,但 SelectedItem 是一个 ComboBoxItem 对象。将一个 String 绑定到 SelectedItem 不会更改 ComboBox 的选定项。因此,如果您想要使用 SelectedComboBoxOption 来获取和设置 ComboBox 的选定项,您需要将 SelectedComboBoxOption 更改为 ComboBoxItem 并在 {x:Bind} 中使用转换器来在 ObjectComboBoxItem 之间进行转换。

转换器可能如下所示:

public class ComboBoxItemConvert : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        return value;
    }

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

XAML 可能如下所示:

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

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel>
            <ComboBox Name="ComboBox"
                      DisplayMemberPath="ComboBoxHumanReadableOption"
                      Header="ComboBox"
                      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>
</Page>

在代码后台:

public sealed partial class MainPage : Page, INotifyPropertyChanged
{
    private ObservableCollection<ComboBoxItem> ComboBoxOptions;

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

    public ComboBoxItem SelectedComboBoxOption
    {
        get
        {
            return _SelectedComboBoxOption;
        }
        set
        {
            if (_SelectedComboBoxOption != value)
            {
                _SelectedComboBoxOption = value;
                RaisePropertyChanged("SelectedComboBoxOption");
            }
        }
    }
    ...
}
如果您只想在中显示所选项,有一个简单的方法。我们可以将的

1
这个完美地运作了!非常感谢您提供的出色解释。作为一个新手,理解为什么要以某种方式完成事情并不总是容易的。 - RonaldA
@Jay,我遇到了相反的问题。初始化后它是空白的,但你可以正常选择。你能看一下这个问题吗?谢谢!http://stackoverflow.com/questions/39090923/why-this-uwp-combobox-can-be-blank-after-initialization-but-works-fine-for-selec - litaoshen

0

默认情况下,x:Bind 被设置为 OneTime。您可以通过将模式简单地设置为 OneWay 来解决这个问题。

Text="{x:Bind SelectedComboBoxOption, Mode=OneWay}"

1
不幸的是,这似乎没有任何区别。此外,由于我最终想要加载一个首选项并在组合框中反映出来,所以我应该使用:'Mode=TwoWay'吗? - RonaldA
@RonaldA 对于SelectedItem保持 Mode=TwoWay,但是对于TextBlock中的Text属性,你必须使用Mode=OneWay - Jakub Krampl

0
另一个解决方案(更像是MVVM)是在你的代码后台创建一个ComboBoxItem类型的对象,将其绑定,并让你的代码后台操作该对象以获取所需的字符串。这样可以避免你必须创建转换器的情况:
C#
public ComboBoxItem ComboBoxItemSelected {get; set;}

XAML
SelectedItem = "{Binding ComboBoxItemSelected, Mode=TwoWay}"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接