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

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

问题描述

我想获得一个组合框用结合,使我最终可以使用它的一些设置工作。我能得到的项目从一个观察的集合和绑定的SelectedItem'到属性的SelectedItem ={X:绑定SelectedComboBoxOption}填充

但是,当我改变选择这不仅仅体现在文本框也必将为这个属性。在其背后的code更改在下拉列表项目时设置一次就推出,但不是财产。我一定是失去了一些东西,但它并不清楚我什么。任何想法?

这是XAML:

 <页
X:类=ComboBoxTest.MainPage
的xmlns =htt​​p://schemas.microsoft.com/winfx/2006/xaml/$p$psentation
的xmlns:X =htt​​p://schemas.microsoft.com/winfx/2006/xaml
XMLNS:地方=使用:ComboBoxTest
的xmlns:D =htt​​p://schemas.microsoft.com/ex$p$pssion/blend/2008
的xmlns:MC =htt​​p://schemas.openxmlformats.org/markup-compatibility/2006
MC:可忽略=D><网格背景={ThemeResource ApplicationPageBackgroundThemeBrush}>
    <&StackPanel的GT;
        <组合框
            NAME =组合框
            的ItemsSource ={X:绑定ComboBoxOptions}
            的SelectedItem ={X:绑定SelectedComboBoxOption,模式=双向}
            SelectedValuePath =ComboBoxOption
            的DisplayMemberPath =ComboBoxHumanReadableOption
            标题=组合框>
        < /组合框>
        < TextBlock的名称=BoundTextblock文本={X:绑定SelectedComboBoxOption}/>
    < / StackPanel的>
< /网格和GT;

这背后是code:

 使用系统;
使用System.Collections.Generic;
使用System.Collections.ObjectModel;
使用System.ComponentModel;
使用System.IO;
使用System.Linq的;
使用System.Runtime.InteropServices.WindowsRuntime;
使用Windows.Foundation;
使用Windows.Foundation.Collections;
使用Windows.UI.Xaml;
使用Windows.UI.Xaml.Controls;
使用Windows.UI.Xaml.Controls.Primitives;
使用Windows.UI.Xaml.Data;
使用Windows.UI.Xaml.Input;
使用Windows.UI.Xaml.Media;
使用Windows.UI.Xaml.Navigation;命名空间ComboBoxTest
{ 公共密封部分类的MainPage:页面,INotifyPropertyChanged的
 {    私人的ObservableCollection< ComboBoxItem> ComboBoxOptions;    公众的MainPage()
    {
        this.InitializeComponent();
        ComboBoxOptions =新的ObservableCollection< ComboBoxItem>();
        ComboBoxOptionsManager.GetComboBoxList(ComboBoxOptions);
    }    公共类ComboBoxItem
    {
        公共字符串ComboBoxOption {搞定;组; }
        公共字符串ComboBoxHumanReadableOption {搞定;组; }
    }    公共类ComboBoxOptionsManager
    {
        公共静态无效GetComboBoxList(的ObservableCollection< ComboBoxItem> ComboBoxItems)
        {
            变种allItems = getComboBoxItems();
            ComboBoxItems.Clear();
            allItems.ForEach(p值=> ComboBoxItems.Add(P));
        }        私人静态列表< ComboBoxItem> getComboBoxItems()
        {
            VAR项目=新的List< ComboBoxItem>();            items.Add(新ComboBoxItem(){ComboBoxOption =选项1,ComboBoxHumanReadableOption =选项1});
            items.Add(新ComboBoxItem(){ComboBoxOption =1选项,ComboBoxHumanReadableOption =选项2});
            items.Add(新ComboBoxItem(){ComboBoxOption =2选项,ComboBoxHumanReadableOption =选择3});            返回的物品;
        }
    }
    字符串_SelectedComboBoxOption =选项1;
    公共字符串SelectedComboBoxOption
    {
        得到
        {
            返回_SelectedComboBoxOption;
        }
        组
        {
            如果(_SelectedComboBoxOption!=值)
            {
                _SelectedComboBoxOption =价值;
                RaisePropertyChanged(SelectedComboBoxOption);
            }
        }
    }    无效RaisePropertyChanged(字符串道具)
    {
        如果(的PropertyChanged!= NULL){PropertyChanged的(这一点,新PropertyChangedEventArgs(丙)); }
    }
    公共事件PropertyChangedEventHandler的PropertyChanged;
 }
}


解决方案

由于@Mike陈奕迅和@kubakista说,你需要设置模式明确。但是,这不会完全解决您的问题。

在您的code,你的 SelectedComboBoxOption 是一个字符串,但的SelectedItem ComboBoxItem 对象。绑定字符串的SelectedItem 不会改变组合框 S的项目。所以,如果你想使用 SelectedComboBoxOption 来获取和设置组合框的选中的项目,您需要更改 SelectedComboBoxOption ComboBoxItem ,并使用 {X:绑定} 来之间的转换对象 ComboBoxItem

的转换,可能会想:

 公共类ComboBoxItemConvert:的IValueConverter
{
    公共对象转换(对象的值,类型TARGETTYPE,对象参数,字符串语言)
    {
        返回值;
    }    公共对象ConvertBack(对象的值,类型TARGETTYPE,对象参数,字符串语言)
    {
        返回值MainPage.ComboBoxItem;
    }
}

的XAML可能会喜欢:

 <第...>
    < Page.Resources>
        <局部:ComboBoxItemConvert X:键=ComboBoxItemConvert/>
    < /Page.Resources>    <网格背景={ThemeResource ApplicationPageBackgroundThemeBrush}>
        <&StackPanel的GT;
            <组合框名称=组合框
                      的DisplayMemberPath =ComboBoxHumanReadableOption
                      标题=组合框
                      的ItemsSource ={X:绑定ComboBoxOptions}
                      的SelectedItem ={X:绑定SelectedComboBoxOption,模式=双向,转换器= {StaticResource的ComboBoxItemConvert}}
                      SelectedValuePath =ComboBoxOption/>
            < TextBlock的名称=BoundTextblock文本={X:绑定SelectedComboBoxOption.ComboBoxHumanReadableOption,模式=单向}/>
        < / StackPanel的>
    < /网格和GT;
< /页>

在code-背后:

 公共密封部分类的MainPage:页面,INotifyPropertyChanged的
{
    私人的ObservableCollection< ComboBoxItem> ComboBoxOptions;    公众的MainPage()
    {
        this.InitializeComponent();
        ComboBoxOptions =新的ObservableCollection< ComboBoxItem>();
        ComboBoxOptionsManager.GetComboBoxList(ComboBoxOptions);
        SelectedComboBoxOption = ComboBoxOptions [0];
    }
    ...
    私人ComboBoxItem _SelectedComboBoxOption;    公共ComboBoxItem SelectedComboBoxOption
    {
        得到
        {
            返回_SelectedComboBoxOption;
        }
        组
        {
            如果(_SelectedComboBoxOption!=值)
            {
                _SelectedComboBoxOption =价值;
                RaisePropertyChanged(SelectedComboBoxOption);
            }
        }
    }
    ...
}

如果你只是想显示的TextBlock 选定的项目,有一个简单的方法。我们可以绑定的TextBlock 文本属性组合框小号的SelectedItem 。而且请注意,的SelectedItem 的类型是 System.Object的 {X:}绑定是强类型,并且将解析路径中的每个步骤的类型。如果返回的类型没有成员,它会在编译时失败。因此,我们需要指定一个铸告诉结合实际对象的类型。但有一个<一个href=\"http://stackoverflow.com/questions/33569454/xbind-and-nested-class-in-a-uwp-application\">issue而投嵌套类 {X:绑定} 。我们可以把 ComboBoxItem 中的MainPage 作为一种解决方法。

 命名空间ComboBoxTest
{
    公共类ComboBoxItem
    {
        公共字符串ComboBoxOption {搞定;组; }
        公共字符串ComboBoxHumanReadableOption {搞定;组; }
    }    公共密封部分类的MainPage:页面,INotifyPropertyChanged的
    {
        ...
    }
}

而在XAML:

 &LT;网格背景={ThemeResource ApplicationPageBackgroundThemeBrush}&GT;
    &LT;&StackPanel的GT;
        &LT;组合框名称=组合框
                  的DisplayMemberPath =ComboBoxHumanReadableOption
                  标题=组合框
                  的ItemsSource ={X:绑定ComboBoxOptions}
                  SelectedValuePath =ComboBoxOption/&GT;
        &LT; TextBlock的名称=BoundTextblock文本={X:绑定ComboBox.SelectedItem(本地:ComboBoxItem.ComboBoxHumanReadableOption),模式=单向}/&GT;
    &LT; / StackPanel的&GT;
&LT; /网格和GT;

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?

This is the 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>

And this is the code behind:

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

解决方案

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

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.

The Convert may like:

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

The XAML may like:

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

In the code-behind:

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

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
    {
        ...
    }
}

And in the 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天全站免登陆