【问题标题】:UWP Combobox binding to SelectedItem propertyUWP 组合框绑定到 SelectedItem 属性
【发布时间】:2016-02-22 15:28:55
【问题描述】:

我正在尝试让组合框与绑定一起使用,以便最终可以将其用于某些设置。我可以从可观察的集合中获取要填充的项目并将“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;
 }
}

【问题讨论】:

    标签: c# xaml binding combobox uwp


    【解决方案1】:

    默认情况下,x:Bind 设置为 OneTime。您只需将模式设置为 OneWay 即可解决此问题。

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

    【讨论】:

    • 不幸的是,这似乎没有什么不同。此外,由于我想最终加载首选项并将其反映在组合框中,我不应该使用:'Mode=TwoWay' 吗?
    • @RonaldA For SelectedItem 保留Mode=TwoWay 但对于TextBlock 中的Text 属性,您必须使用Mode=OneWay
    【解决方案2】:

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

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

    Convert 可能会喜欢:

    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:Bind} 中有一个issue while cast 嵌套类。我们可以将ComboBoxItem 排除在MainPage 之外作为一种解决方法。

    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>
    

    【讨论】:

    • 这很完美!也非常感谢您的精彩解释。作为一个新手,要理解为什么事情会以某种方式完成并不总是那么容易。
    • @Jay,我遇到了相反的问题。初始化后为空白,可以正常选择。请你看看这个问题好吗?谢谢! stackoverflow.com/questions/39090923/…
    【解决方案3】:

    另一个解决方案(更像 MVVM)是在您的代码隐藏中创建一个 ComboBoxItem 类型的对象,绑定到该对象,然后让您的代码隐藏操作该对象以获得所需的字符串。这将使您不必创建转换器:

    C#
    public ComboBoxItem ComboBoxItemSelected {get; set;}
    
    XAML
    SelectedItem = "{Binding ComboBoxItemSelected, Mode=TwoWay}"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-25
      • 1970-01-01
      • 2017-04-26
      • 1970-01-01
      • 2017-11-08
      相关资源
      最近更新 更多