2015-06-24 2 views
5

Ich habe ein Problem beim Versuch, 2 oder mehr Comboboxen SelectedValue an eine Eigenschaft zu binden, die null ist. Nur 1 der an diese Eigenschaft gebundenen Comboboxen zeigt den tatsächlichen Wert an.WPF ComboBox SelectedValue Bindung mit Nullwert zeigt leer

Unten ist mein Xaml, wo ich DataTemplate verwenden, um eine Combobox für die Präsentation des ViewModel auszuwählen.

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> 

Und den Code hinter:

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

Jetzt frage ich mich, warum nur 1 von ihnen den NULL-Wert beim Start zeigen kann? Ich kann den Wert in jedem von ihnen ändern, und sie werden alle mit dem Wert in der Eigenschaft synchronisiert - wenn ich 1 und dann zurück zu NULL wählen, werden sie alle NULL zeigen. Es scheint, als ob nur der Anfangswert nicht korrekt angezeigt wird.

Wenn ich vermeiden, DataTemplate zu verwenden, funktioniert die Bindung auch. Weiß jemand, warum das DAtaTemplate sich so verhält?

Antwort

3

Interessantes Problem.

Grundsätzlich scheint dies durch Ihre Wahl zu null als einer der auswählbaren Werte verursacht werden. null hat natürlich eine besondere Bedeutung für C#, .NET und WPF. Das Problem beinhaltet auch die Reihenfolge, in der die Initialisierung des Elements ComboBox erfolgt. Die SelectedValuePath Eigenschaft wird nach die SelectedValue Eigenschaft initialisiert.

Dies bedeutet, dass Ihr Programm sind und die ComboBox Elemente beginnend erstellt, wenn null zum SelectedValue Eigenschaft durch seine Bindung zugeordnet ist, wird die ComboBox noch nicht genügend Informationen haben, diesen Wert als ein legitimes Element Auswahl zu handhaben. Stattdessen interpretiert es es als keine Auswahl.

Warum wird die letzteComboBox immer noch so initialisiert, wie Sie möchten? Ich bin mir nicht wirklich sicher, und zum Teufel, ich habe das nicht sehr gründlich untersucht. Ich könnte spekulieren, aber die Wahrscheinlichkeit, dass ich richtig rate, scheint niedrig zu sein, also werde ich mich nicht darum kümmern. Da es die Anomalie und nicht unbedingt im Einklang mit dem erwarteten Verhalten ist (basierend auf obigem, selbst wenn das Verhalten das gewünschte Verhalten ist), werde ich es auf eine von vielen WPFs "Macken" bringen. :)

fand ich mehrere Workarounds für das Problem:

  • nicht null als auswählbare Wert anwenden. Wenn jeder auswählbare Wert ungleich null ist, wird der Nicht-Null-Wert, der zum Initialisieren der Eigenschaft jedes Elements verwendet wurde, beibehalten, und wenn die SelectedValuePath initialisiert wird, ist die aktuelle Auswahl für ComboBox korrekt eingestellt.
  • Verwenden Sie nicht SelectedValuePath. Binden Sie stattdessen einfach an SelectedItem und initialisieren Sie die Value-Eigenschaft mit der gewünschten Klasseninstanz SelectableValue (z. B. die erste in der Liste).
  • Aktualisieren Sie im ComboBox Ereignis Loaded das Ziel der Bindung.

Die ersten beiden sind signifikante Abweichungen von Ihrem aktuellen Design. Persönlich, wenn überhaupt möglich, würde ich mit dem einen oder dem anderen gehen. Es scheint mir, dass es eine klare Gefahr bei der Verwendung von null als auswählbaren Wert in einem ComboBox gibt, und dies ist möglicherweise nicht die einzige Seltsamkeit, in die Sie geraten. Auf lange Sicht kann die Wartung dieses Teils des Codes viel mehr kosten, wenn Sie weiterhin null verwenden.

Das heißt, die dritte Option funktioniert, und wenn Sie Glück haben, ist die einzige echte Gefahr bei der Verwendung null bei der Initialisierung. Mein Vorschlag Behelfslösung für diese Option würde wie folgt aussehen:

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

Diese WPF zwingt das Ziel zu aktualisieren (dh die SelectedValue Eigenschaft der Kontrolle). Da zu diesem Zeitpunkt die SelectedValuePath festgelegt wurde, aktualisiert die Zuweisung null der Eigenschaft dieses Mal korrekt das ausgewählte Element für die ComboBox.


Übrigens, ich würde dringend empfehlen, dass Sie die Namen der Value Eigenschaften in Ihren Modellen disambiguieren. Zwei verschiedene Value Eigenschaften, die für Bindungen in einem einzelnen XAML-Element verwendet werden, sind sehr verwirrend. Ich würde zum Beispiel SelectedValue und ItemValue für die Klasse PropertyValueViewModel bzw. SelectableValue verwenden.

+0

Danke. Ich werde dies als meine Lösung bezeichnen, da es ein paar Wege gibt, das Problem zu lösen, und eine nette Erklärung für das Problem. – Patrick