带有null值的WPF ComboBox SelectedValue绑定显示为空白

时间:2015-06-24 00:33:15

标签: c# wpf binding combobox datatemplate

尝试将2个或更多Comboboxes SelectedValue绑定到属性时出现问题,即null。 只有1个绑定到此属性的组合框将显示实际值。

下面是我的Xaml,我使用DataTemplate选择一个Combobox来呈现viewModel。

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

现在我想知道为什么只有其中一个可以在启动时显示NULL值? 我可以更改其中任何一个的值,它们都会与属性中的值同步 - 如果我选择1然后再返回NULL,它们都将显示为NULL。 似乎只是初始值没有正确显示。

如果我避免使用DataTemplate,那么绑定也会起作用。 有谁知道为什么DAtaTemplate会这样做?

1 个答案:

答案 0 :(得分:3)

有趣的问题。

从根本上说,这似乎是由于您选择使用null作为可选值之一。当然,null对于C#,. NET和WPF具有特殊意义。该问题还涉及ComboBox元素的初始化完成的顺序。 <{1}}属性在 SelectedValuePath属性后初始化

这意味着,当您的程序启动并创建了SelectedValue元素时,ComboBox通过绑定将null属性分配给SelectedValue时,ComboBox会还没有足够的信息来处理作为合法项目选择的价值。相反,它将其解释为根本没有选择。

为什么 last ComboBox仍然按照您想要的方式进行初始化?我不太确定......我没有对此进行过很长时间的调查。我可以猜测,但我的猜测正确的几率似乎很低,所以我不会打扰。由于它是异常并且未必与预期行为保持一致(基于上述情况,即使行为是期望的行为),我也会将其归结为WPF之一&# 39;许多&#34;怪癖&#34;。 :)

我找到了几个解决这个问题的方法:

  • 请勿使用null作为可选值。如果每个可选值都为非null,则保留用于初始化每个元素的SelectedValue属性的非null值,并且在SelectedValuePath初始化时,ComboBox的当前选择1}}设置正确。
  • 不要使用SelectedValuePath。相反,只需绑定到SelectedItem并使用所需的Value类实例(例如列表中的第一个)初始化SelectableValue属性。
  • ComboBox&#39; 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类使用PropertyValueViewModelSelectableValue