UWP 组合框绑定到 SelectedItem 属性
UWP Combobox binding to SelectedItem property
我正在尝试让组合框与绑定一起使用,以便我最终可以将它用于某些设置。我可以从可观察的集合中获取要填充的项目并将 '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;
}
}
默认情况下,x:Bind
设置为 OneTime
。您可以通过简单地将模式设置为 OneWay
.
来解决这个问题
Text="{x:Bind SelectedComboBoxOption, Mode=OneWay}"
正如@Mike Eason 和@kubakista 所说,您需要明确设置 Mode
。但这并不能完全解决您的问题。
在您的代码中,您的 SelectedComboBoxOption
是一个字符串,但 SelectedItem
是一个 ComboBoxItem
对象。将 String
绑定到 SelectedItem
不会更改 ComboBox
的选定项目。所以如果你想使用SelectedComboBoxOption
获取和设置ComboBox
的选中项,你需要将SelectedComboBoxOption
更改为ComboBoxItem
并在{x:Bind}
中使用Convert在 Object
和 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
中显示所选项目,有一个简单的方法。我们可以将 TextBlock
的 Text
属性 绑定到 ComboBox
的 SelectedItem
。请注意 SelectedItem
的类型是 System.Object
并且 {x:Bind}
是强类型的,并且会解析路径中每个步骤的类型。如果返回的类型没有成员,它会在编译时失败。所以我们需要指定一个强制转换来告诉绑定对象的真实类型。但是有一个 while cast nested class in {x:Bind}
。我们可以将 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>
另一种解决方案(更像 MVVM)是在您的代码隐藏中创建一个 ComboBoxItem 类型的对象,绑定到该对象,然后让您的代码隐藏操作该对象以获得所需的字符串。这将使您不必创建转换器:
C#
public ComboBoxItem ComboBoxItemSelected {get; set;}
XAML
SelectedItem = "{Binding ComboBoxItemSelected, Mode=TwoWay}"
我正在尝试让组合框与绑定一起使用,以便我最终可以将它用于某些设置。我可以从可观察的集合中获取要填充的项目并将 '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;
}
}
默认情况下,x:Bind
设置为 OneTime
。您可以通过简单地将模式设置为 OneWay
.
Text="{x:Bind SelectedComboBoxOption, Mode=OneWay}"
正如@Mike Eason 和@kubakista 所说,您需要明确设置 Mode
。但这并不能完全解决您的问题。
在您的代码中,您的 SelectedComboBoxOption
是一个字符串,但 SelectedItem
是一个 ComboBoxItem
对象。将 String
绑定到 SelectedItem
不会更改 ComboBox
的选定项目。所以如果你想使用SelectedComboBoxOption
获取和设置ComboBox
的选中项,你需要将SelectedComboBoxOption
更改为ComboBoxItem
并在{x:Bind}
中使用Convert在 Object
和 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
中显示所选项目,有一个简单的方法。我们可以将 TextBlock
的 Text
属性 绑定到 ComboBox
的 SelectedItem
。请注意 SelectedItem
的类型是 System.Object
并且 {x:Bind}
是强类型的,并且会解析路径中每个步骤的类型。如果返回的类型没有成员,它会在编译时失败。所以我们需要指定一个强制转换来告诉绑定对象的真实类型。但是有一个 {x:Bind}
。我们可以将 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>
另一种解决方案(更像 MVVM)是在您的代码隐藏中创建一个 ComboBoxItem 类型的对象,绑定到该对象,然后让您的代码隐藏操作该对象以获得所需的字符串。这将使您不必创建转换器:
C#
public ComboBoxItem ComboBoxItemSelected {get; set;}
XAML
SelectedItem = "{Binding ComboBoxItemSelected, Mode=TwoWay}"