具有null值的WPF组合框SelectedValue绑定显示为空
本文关键字:绑定 显示 SelectedValue null 值的 WPF 组合 具有 | 更新日期: 2023-09-27 17:59:11
我在尝试将2个或多个组合框SelectedValue绑定到一个属性时遇到问题,该属性为null。绑定到此属性的组合框中只有1个会显示实际值。
下面是我的Xaml,我使用DataTemplate选择一个组合框来表示视图模型。
Xaml:
<Window x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Test"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate DataType="{x:Type local:PropertyValueViewModel}">
<ComboBox SelectedValue="{Binding Value}" ItemsSource="{Binding SelectableValues}" DisplayMemberPath="Description" SelectedValuePath="Value"/>
</DataTemplate>
</Window.Resources>
<StackPanel>
<Label Content="These uses template:"></Label>
<ContentPresenter Content="{Binding ValueSelector}"></ContentPresenter>
<ContentPresenter Content="{Binding ValueSelector}"></ContentPresenter>
<ContentPresenter Content="{Binding ValueSelector}"></ContentPresenter>
</StackPanel>
以及背后的代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ValueSelector = new PropertyValueViewModel()
{
SelectableValues = new List<SelectableValue>()
{
new SelectableValue("NULL", null),
new SelectableValue("1", 1)
},
Value = null
};
DataContext = this;
}
public static readonly DependencyProperty ValueSelectorProperty = DependencyProperty.Register(
"ValueSelector", typeof(PropertyValueViewModel), typeof(MainWindow), new PropertyMetadata(default(PropertyValueViewModel)));
public PropertyValueViewModel ValueSelector
{
get { return (PropertyValueViewModel)GetValue(ValueSelectorProperty); }
set { SetValue(ValueSelectorProperty, value); }
}
}
/// <summary>
/// My viewModel
/// </summary>
public class PropertyValueViewModel
{
public object Value { get; set; }
public object SelectableValues { get; set; }
}
/// <summary>
/// The items in the combobox
/// </summary>
public class SelectableValue
{
public SelectableValue(string header, object value)
{
Value = value;
Description = header;
}
public object Value { get; set; }
public string Description { get; set; }
}
现在我想知道为什么只有1个可以在启动时显示NULL值?我可以更改其中任何一个的值,它们都将与属性中的值同步——如果我选择1,然后返回NULL,它们都会显示NULL。似乎只有初始值没有正确显示。
如果我避免使用DataTemplate,那么绑定也可以工作。有人知道DAtaTemplate为什么会这样做吗?
有趣的问题。
从根本上讲,这似乎是由于您选择使用null
作为可选值之一而导致的。当然,null
对于C#有着特殊的意义。NET和WPF。该问题还涉及对ComboBox
元素进行初始化的顺序。SelectedValuePath
属性在SelectedValue
属性之后初始化。
这意味着,当程序启动并创建ComboBox
元素时,当通过绑定将null
分配给SelectedValue
属性时,ComboBox
还没有足够的信息将该值作为合法的项目选择进行处理。相反,它将其解释为根本没有选择。
为什么最后一个ComboBox
仍然按照您想要的方式初始化?我真的不确定;我对此没有深入调查。我可以推测,但我猜对的几率似乎很低,所以我不会麻烦。由于这是一种反常现象,不一定与预期行为一致(基于上述,即使行为是所需的行为),我将其归因于WPF的许多"怪癖"之一。:)
我找到了几个解决问题的方法:
- 不要将
null
用作可选值。如果每个可选值都是非空值,则用于初始化每个元素的SelectedValue
属性的非空值将被保留,并且当初始化SelectedValuePath
时,ComboBox
的当前选择将被正确设置 - 不要使用
SelectedValuePath
。相反,只需绑定到SelectedItem
,并使用所需的SelectableValue
类实例(例如列表中的第一个)初始化Value
属性 - 在
ComboBox
的Loaded
事件中,刷新绑定的目标
前两个与您当前的设计有很大的不同。就我个人而言,如果可能的话,我会选择其中一个。在我看来,使用null
作为ComboBox
中的可选值显然有危险,这可能不是你遇到的唯一奇怪之处。从长远来看,如果继续使用null
,维护这部分代码的成本可能会高得多。
也就是说,第三个选项确实有效,如果幸运的话,使用null
的唯一真正危险是初始化。我提议的解决方案是这样的:
XAML:
<DataTemplate DataType="{x:Type local:PropertyValueViewModel}">
<ComboBox SelectedValue="{Binding Value}"
ItemsSource="{Binding SelectableValues}"
DisplayMemberPath="Description"
SelectedValuePath="Value"
Loaded="comboBox_Loaded"/>
</DataTemplate>
C#:
private void comboBox_Loaded(object sender, RoutedEventArgs e)
{
ComboBox comboBox = (ComboBox)e.OriginalSource;
BindingOperations.GetBindingExpression(comboBox, ComboBox.SelectedValueProperty)
.UpdateTarget();
}
这迫使WPF更新目标(即控件的SelectedValue
属性)。由于此时已经设置了SelectedValuePath
,因此将null
分配给该属性将正确地更新ComboBox
的所选项目。
顺便说一句,我强烈建议您消除模型中Value
属性名称的歧义。在一个XAML元素中为绑定使用两个不同的Value
属性是非常令人困惑的。例如,我将分别使用SelectedValue
和ItemValue
作为PropertyValueViewModel
类和SelectableValue
类。