2017-03-16 1 views
2

Ich habe ein MVVM-Projekt mit einem View und einem ViewModel in seinem DataContext.Mehrstufige Bindung von ViewModel zu Custom-Control zu Controls auf ControlTemplate funktioniert nicht

In diesem Projekt habe ich eine Klasse ComboBoxCustom, die von ComboBox erbt. Ich definiere einige zusätzliche Funktionen in meiner ComboBoxCustom Klasse.

Zu diesem ComboBoxCustom Klasse ich eine Steuerelementvorlage zuweisen, um das Aussehen zu definieren.

Der (vereinfachte) Stil der (vereinfacht) Steuerelementvorlage definiert, wie folgt aussieht:

<Style TargetType="{x:Type lib:ComboBoxCustom}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type lib:ComboBoxCustom}"> 
       <StackPanel> 
        <TextBlock Text="{TemplateBinding TextPropertyInComboBoxCustom}"/> 

        <ComboBox DataContext="{TemplateBinding DataContext}" 
           ItemsSource="{TemplateBinding ItemsSource}" 
           DisplayMemberPath="{TemplateBinding DisplayMemberPath}" 
           SelectedValuePath="{TemplateBinding SelectedValuePath}" 
           SelectedValue="{TemplateBinding SelectedValue}" 
           SelectedItem="{TemplateBinding SelectedItem}"/> 
       </Grid> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

, die in einem ResourceDictionary befindet. Die echte Kontrollschablone hat einige zusätzliche Merkmale, die weggelassen werden, da sie für die Frage nicht relevant sind.

Ich benutze diese ComboBoxCustom Kontrolle in meiner Ansicht mit:

<lib:ComboBoxCustom ItemsSource="{Binding MyObservableCollectionOfMyObjects}" 
        TextPropertyInComboBoxCustom="MyText" 
        DisplayMemberPath="MyDescription" 
        SelectedValuePath="MyValue" 
        SelectedItem="{Binding SelectedMyObject, Mode=TwoWay}"/> 

Der Blick in Ordnung ist, und alle Elemente erhalten in der ComboBox geladen, die ich auswählen kann.

Das Problem ist, dass, wenn ich ein anderes Element in der ComboBox auswählen, die Eigenschaft SelectedMyObject in meinem ViewModel nicht aktualisiert wird und folglich seine Setter nicht aufgerufen wird. Daher ist die (korrekte) Information über das ausgewählte Objekt in meinem ViewModel nicht verfügbar.

Wenn ich <ComboBox .../> (ohne TextPropertyInComboBoxCustom Eigenschaft) statt <lib:ComboBoxCustom .../> alles funktioniert nur gut, aber dann habe ich nicht die zusätzliche Funktionalität in ComboBoxMessage definiert, die ich brauche.

Kann mir jemand sagen, was los ist und wie ich dieses Problem beheben kann, so dass ich ComboBoxMessage aus meiner Sicht verwenden kann? Vorzugsweise ohne das MVVM-Muster zu brechen.

Vielen Dank!

+1

'{Template SelectedItem}' ist ein OneWay Bindung (siehe [Dieser Beitrag] (http://stackoverflow.com/questions/5913176/in-wpf-why-doesnt-templatebinding- Work-Where-Binding-tut)). Ändern Sie es in eine Bindung mit RelativeSource = TemplatedParent wie in der angenommenen Antwort vorgeschlagen – ASh

+0

Danke ASh, das war in der Tat das Problem. – Stefan

+0

':)'. Was ist mit 'SelectedValue =" {TemplateBinding SelectedValue} "? Es ist die gleiche Sache – ASh

Antwort

2

Thanx zu Ashs Kommentar und Informationen in this post.

Das Problem ist, dass die TemplateBinding ist eine Möglichkeit. Daher können alle Informationen aus dem ViewModel in die Steuerelemente in der Vorlage gelangen. Aber nicht umgekehrt.

Die Lösung ist eine normale Bindung angeben, wie:

SelectedItem ="{Binding SelectedItem, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" 

Rechenblatt die gleiche tut etwa als TemplateBinding aber zwei Wege.

Die Steuervorlage geworden:

<Style TargetType="{x:Type lib:ComboBoxCustom}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type lib:ComboBoxCustom}"> 
       <StackPanel> 
        <TextBlock Text="{TemplateBinding TextPropertyInComboBoxCustom}"/> 

        <ComboBox DataContext="{TemplateBinding DataContext}" 
           ItemsSource="{TemplateBinding ItemsSource}" 
           DisplayMemberPath="{TemplateBinding DisplayMemberPath}" 
           SelectedValuePath="{TemplateBinding SelectedValuePath}" 
           SelectedValue="{TemplateBinding SelectedValue}" 
           SelectedItem ="{Binding SelectedItem, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"/> 
       </Grid> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

Ich bin nicht sicher über die SelectedValue Eigenschaft though.Mit der Vorlage wie dieser funktioniert es, wenn ich die SelectedValue Eigenschaft oder die SelectedItem Eigenschaft verwende.

Die Option Mode=TwoWay kann in der Ansicht weggelassen werden, da der Standardbindungsmodus für SelectedItem bereits zweiseitig ist. Die Sichtlinie wird:

<lib:ComboBoxCustom ItemsSource="{Binding MyObservableCollectionOfMyObjects}" 
        TextPropertyInComboBoxCustom="MyText" 
        DisplayMemberPath="MyDescription" 
        SelectedValuePath="MyValue" 
        SelectedItem="{Binding SelectedMyObject}"/> 
1

Bind SelectedValue an der Immobilie in Ansichtsmodell

SelectedValue="{Binding SelectedMyObject, Mode=TwoWay}" 

in Ihrem lib: ComboBoxCustom

+0

Danke, das Problem besteht weiter. Das 'SelectedMyObject' ist noch nicht aktualisiert. Dies liegt daran, dass die Template-Bindung, die 'ComboBox' in der ControlTemplate mit' ComboBoxCustom' verbindet, OneWay ist. Daher wird die Bindung in der Ansicht in 'ComboBoxCustom' nie die Änderung erhalten, um neue Informationen von den Steuerelementen in der Vorlage weiterzuleiten. – Stefan

Verwandte Themen