2016-06-20 7 views
0

Ich habe ein List-Feld an ein beobachtbares Objekt in meinem ViewModel gebunden. Wenn der Benutzer ein Element in der Listbox auswählt, löst das SelectedItem die Eigenschaft "SelectedSandwich" aus. Der Wert wird in einem privaten Feld gespeichert. Die Eigenschaften SandwichName und Description sind Eigenschaften des Sandwich-Objekts. Ich möchte, dass Textblöcke in meiner Ansicht ausgewählten Sandwichnamen und Preis anzeigen, aber ich möchte diese Textblöcke nicht an das Listenfeldelement binden. Hier ist die Ansicht: 'Wie greife ich auf Eigenschaften eines Objekts zu, das aus einer ListBox WPF MVVM ausgewählt wird

<Window.DataContext> 
    <vm:SandwichVM/> 
</Window.DataContext> 

<Window.Resources> 

    <DataTemplate x:Key="lstSandwich"> 
     <Border BorderThickness="3" 
       CornerRadius="4" 
       HorizontalAlignment="Stretch" 
       BorderBrush="Blue"> 
      <TextBlock HorizontalAlignment="Stretch"> 
       <Run Text="{Binding SandwichName}"/> 
       <Run Text=" | " /> 
       <Run Text="{Binding Description}" /> 
       <Run Text=" | " /> 
       <Run Text="{Binding Price}" /> 
      </TextBlock> 
     </Border> 
    </DataTemplate> 

    <DataTemplate x:Key="menu" > 
     <Border> 
      <TextBlock HorizontalAlignment="Stretch"> 
       <Run Text="{Binding SandwichName}"/> 
       <Run Text="{Binding Price}" /> 
      </TextBlock> 
     </Border> 
    </DataTemplate> 

</Window.Resources> 

<Grid> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="Auto"/> 
    </Grid.ColumnDefinitions> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="*" /> 
     <RowDefinition Height="2*"/> 
    </Grid.RowDefinitions> 

    <ListBox Grid.Row="0" x:Name="cboMenu" 
      ItemsSource="{Binding Sandwiches}" 
      SelectedItem="{Binding SelectedSandwich, Mode=TwoWay}" 
      ItemTemplate="{StaticResource lstSandwich}" 
      Margin="3"> 
    </ListBox> 

    <Grid Grid.Row="1"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="*"/> 
      <RowDefinition Height="3*"/> 
     </Grid.RowDefinitions> 

     <TextBlock Grid.Row="0" 
        HorizontalAlignment="Center" 
        VerticalAlignment="Center" 
        FontStretch="ExtraExpanded" 
        FontFamily="Verdana" 
        FontSize="22" 
        > 
      <Run Text="Your Selection"/> 
     </TextBlock> 
     <Grid Grid.Row="1"> 
      <ContentControl 
       ContentTemplate="{StaticResource menu}" 
       HorizontalAlignment="Stretch" 
       Margin="5,0,5,0"> 
      </ContentControl> 
      </Grid> 
     </Grid> 


    </Grid> 
</Window>' 

Hier ist das Viewmodel:

'class SandwichVM : INotifyPropertyChanged 
{ 
    private Sandwich _selectedSandwich; 
    private ObservableCollection<Sandwich> _sandwiches; 



    public ObservableCollection<Sandwich> Sandwiches 
    { 
     get { return _sandwiches; } 
    } 


    public SandwichVM() 
    { 
     //fake data for the list 
     _sandwiches = new ObservableCollection<Sandwich>(); 
     _sandwiches.Add(new Sandwich("Pastrami", "Stacked high on rye bread  with a touch of mustard.", 8.50)); 
     _sandwiches.Add(new Sandwich("Tuna", "Fresh tuna salad on wheat with slice of cheddar cheese.", 6.50)); 
     _sandwiches.Add(new Sandwich("Steak", "Sliced grilled steak with sauteed mushrooms and onions.", 9.50)); 
     _sandwiches.Add(new Sandwich("Chicken Salad", "Juicy chunks of chicken breast, onions, fruit.", 6.50)); 
     _sandwiches.Add(new Sandwich("Buffalo Chicken", "Caliente! Fried chicken breast slathered with hot buffalo wing sauce.", 8.50)); 
     _sandwiches.Add(new Sandwich("Tofu", "I don't know how to make a tofu sandwich.", 1.50)); 

    } 

    public Sandwich SelectedSandwich 
    { 
     get { return _selectedSandwich; } 
     set 
     { 
      if (_selectedSandwich != value) 
      { 
       _selectedSandwich = value; 
       RaisePropertyChangedEvent("SelectedSandwich"); 
      } 
     } 
    } 

    public string SandwichName 
    { 
     get { return _selectedSandwich.SandwichName; } 
     set 
     { 
      _selectedSandwich.SandwichName = value; 
      RaisePropertyChangedEvent("SandwichName"); 
     } 

    } 

    public string Description 
    { 
     get { return _selectedSandwich.Description; } 
     set 
     { 
      _selectedSandwich.Description = value; 
      RaisePropertyChangedEvent("Description"); 
     } 
    } 

    public string Price 
    { 
     get { return _selectedSandwich.Price.ToString(); } 
     set 
     { 
      _selectedSandwich.Price = Convert.ToDouble(value); 
      RaisePropertyChangedEvent("Price"); 
     } 
    } 


    public event PropertyChangedEventHandler PropertyChanged; 

    protected void RaisePropertyChangedEvent(string propertyName) 
    { 
     var handler = PropertyChanged; 
     if (handler != null) 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
    }' 

Ich versuchte, die RaisePropertyChangedEvent in dem Setter für die drei Eigenschaften setzen (obwohl ich sie nur lesen müssen), aber die Setter werden nie ausgeführt. Tatsächlich wird der Setter für die SelectedSandwich -Eigenschaft nie ausgeführt. Der Get wird jedes Mal ausgeführt. Ich bin durch den Code gegangen, kann aber nicht sehen, wo das Problem liegt. Vielen Dank für Ihre Hilfe.

Antwort

0

Vielleicht ist es mir nicht klar, aber die einzige Eigenschaft, die Sie von UI einstellen, ist die SelectedSandwich-Eigenschaft. Wenn es richtig eingestellt wird, wenn Sie das ausgewählte Listbox-Element ändern, dann warum nicht an das SelectedSandwich von der anderen Stelle binden?

Also, wenn Sie einige Textblöcke in Ihrer Ansicht nach wollen versuchen zeigen ausgewählte sandwichname und Preis nur so etwas wie:

<TextBlock Text="{Binding SelectedSandwich.Name}"/> 
<TextBlock Text="{Binding SelectedSandwich.Price}"/> 

Oder wenn Sie Ihre vorbereiteten Datatemplate verwenden:

<DataTemplate DataType="{x:Type sandwichVMNamespace:Sandwich}"> 
    <Border> 
     <TextBlock HorizontalAlignment="Stretch"> 
      <Run Text="{Binding SandwichName}"/> 
      <Run Text="{Binding Price}" /> 
     </TextBlock> 
    </Border> 
</DataTemplate> 

<Grid Grid.Row="1"> 
    <ContentControl 
     Content="{Binding SelectedSandwich}" 
     HorizontalAlignment="Stretch" 
     Margin="5,0,5,0"> 
    </ContentControl> 
</Grid> 

Und Sie sind fertig ...

+0

Ihr erstes Beispiel war einer meiner Versuche. Ich bekomme nichts. Ich suche nach einer Art Tippfehler. Es gibt etwas sehr einfaches, das ich vermisse. Ihr zweites Beispiel wird nicht ausgeführt oder wird nicht kompiliert, je nachdem, was ich mache. Der Namespace ist ComboBox (ich weiß, aber ich begann mit einer Combobox). Ich habe gerade bemerkt, dass die Oberseite des Viewmodels nicht da ist. Ich habe xmlns: vm = "clr-namespace: ComboBox.ViewModel". Dann, wie Sie sehen können, habe ich den Datenkontext im Fenster festgelegt. Also verstehe ich nicht den "x: Type", den Sie vorschlagen. – ScottinTexas

+0

Die DataTemplate ist diejenige, die Sie aufgerufen haben x: Key = "menu" und das Grid ist das, das Sie unten auf der xaml-Seite haben, fügen Sie es einfach ein. Es gibt keinen Grund, warum es nicht kompilieren sollte ... Machen Sie sich keine Sorgen mit x: Geben Sie die wichtige Think ist "SandwichVMNamespace: Sandwich" müssen Sie den Namespace Ihrer Sandwich-Klasse wie Sie zuvor, vielleicht etwas wie xmlns: sandwichVMNamespace = " clr-namespace: ComboBox.ViewModel ". Und es ist alles wegen dem tollen wpf getan ... –

Verwandte Themen