UWP 组合框绑定到 SelectedItem 属性 [英] UWP Combobox binding to SelectedItem property

查看:21
本文介绍了UWP 组合框绑定到 SelectedItem 属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用组合框进行绑定,以便我最终可以将其用于某些设置.我可以从可观察集合中获取要填充的项目并将SelectedItem"绑定到属性 SelectedItem="{x:Bind SelectedComboBoxOption}"

I am trying to get a combobox to work with binding so that I can eventually use it for some settings. I can get the items to populate from an observable collection and bind 'SelectedItem' to a property SelectedItem="{x:Bind SelectedComboBoxOption}"

但是当我更改选择时,这不会反映在也绑定到此属性的文本框中.在它后面的代码中,在启动时设置一次属性,但在更改组合框中的项目时不会设置.我一定错过了一些东西,但我不清楚是什么.有什么想法吗?

But when I change the selection this is not reflected in the textbox also bound to this property. In the code behind it sets the property once on launch but not when changing items in the combobox. I must be missing something but it is not clear to me what. Any ideas?

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

推荐答案

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

As @Mike Eason and @kubakista said, you need set Mode explicitly. But this won't fix your issue completely.

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

In your code, your SelectedComboBoxOption is a string, but the SelectedItem is a ComboBoxItem object. Binding a String to SelectedItem won't change ComboBox's selected item. So if you want to use SelectedComboBoxOption to get and set ComboBox's selected item, you need to change SelectedComboBoxOption to ComboBoxItem and use a Convert in {x:Bind} to convert between Object and ComboBoxItem.

转换者可能喜欢:

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");
            }
        }
    }
    ...
}

如果您只想在 TextBlock 中显示所选项目,有一个简单的方法.我们可以将TextBlockText 属性绑定到ComboBoxSelectedItem.并且请注意,SelectedItem 的类型是 System.Object 并且 {x:Bind} 是强类型的,并且会解析每个踏入一条道路.如果返回的类型没有成员,它将在编译时失败.所以我们需要指定一个强制转换来告诉绑定对象的真实类型.但是有一个问题而在{x:绑定}.我们可以将 ComboBoxItem 放在 MainPage 之外作为解决方法.

If you just want to show selected item in TextBlock, there is an easy way. We can bind TextBlock's Text property to ComboBox's SelectedItem. And please note that SelectedItem's type is System.Object and {x:Bind} is strongly typed, and will resolve the type of each step in a path. If the type returned doesn’t have the member, it will fail at compile time. So we need to specify a cast to tell binding the real type of the object. But there is an issue while cast nested class in {x:Bind}. We can put ComboBoxItem out of MainPage as a workaround.

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

    public sealed partial class MainPage : Page, INotifyPropertyChanged
    {
        ...
    }
}

在 XAML 中:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel>
        <ComboBox Name="ComboBox"
                  DisplayMemberPath="ComboBoxHumanReadableOption"
                  Header="ComboBox"
                  ItemsSource="{x:Bind ComboBoxOptions}"
                  SelectedValuePath="ComboBoxOption" />
        <TextBlock Name="BoundTextblock" Text="{x:Bind ComboBox.SelectedItem.(local:ComboBoxItem.ComboBoxHumanReadableOption), Mode=OneWay}" />
    </StackPanel>
</Grid>

这篇关于UWP 组合框绑定到 SelectedItem 属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆