2016-04-18 6 views
0

Ich versuche, das Model View Viewmodel zu implementieren. Aber ich kann es nicht zur Arbeit bringen.Probleme mit MVVM, Bindung zeigt nicht

Das ist mein Modell und die Basisklasse:

namespace GridCity.GUI { 
    class DateInfoViewModel : PropertyChangedBase { 
     public DateInfoViewModel(DateInfoModel model) { 
      Model = model; 
     } 
     public DateInfoModel Model { get; private set; } 
    } 
} 

Und das ist meine Ansicht:: set

<UserControl x:Class="GridCity.GUI.DateInfoView" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:GridCity.GUI" 
      mc:Ignorable="d" 
      d:DesignHeight="60" d:DesignWidth="150"> 
    <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="150"></ColumnDefinition> 
     </Grid.ColumnDefinitions> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="30"></RowDefinition> 
      <RowDefinition Height="30"></RowDefinition> 
     </Grid.RowDefinitions> 
     <Label Grid.Row="0" Grid.Column="0" FontWeight="ExtraBold" Content="{Binding Model.Date}"></Label> 
     <Label Grid.Row="1" Grid.Column="0" FontWeight="ExtraBold" Content="TEST"></Label> 
    </Grid> 
</UserControl> 

ich meine view.DataContext in

namespace GridCity.GUI { 
    class DateInfoModel : PropertyChangedBase { 
     private string _Date = string.Empty; 

     public string Date { 
      get { 
       return _Date; 
      } 
      set { 
       if (_Date != value) { 
        _Date = value; 
        OnPropertyChanged(nameof(Date)); 
        System.Console.WriteLine(_Date); 
       } 
      } 
     } 
    } 
} 

namespace GridCity.GUI { 
    using System.ComponentModel; 
    public abstract class PropertyChangedBase : INotifyPropertyChanged { 
     public event PropertyChangedEventHandler PropertyChanged; 

     protected internal void OnPropertyChanged(string propertyName) { 
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
      System.Console.WriteLine("OnPropertyChanged: " + propertyName); 
     } 
    } 
} 

Das ist mein Viewmodel ist MainWindow-Konstruktor:

public MainWindow() { 
    InitializeComponent(); 

    DateInfoView view = new DateInfoView(); 
    Game.DateInfoModel = new DateInfoModel(); 
    DateInfoViewModel viewModel = new DateInfoViewModel(Game.DateInfoModel); 

    view.DataContext = viewModel; 
} 

Ich kann das zweite Etikett (TEST) sehen, so scheint die Benutzerkontrolle in der Theorie zu funktionieren. Ich sehe jedoch nichts auf dem ersten Etikett. Ich kann Ausgänge auf der Konsole jedoch sehen, wenn _Date geändert wird und OnPropertyChanged aufgerufen wird.

Was fehlt mir?

+0

Wo/wie setzen Sie 'DataContext' auf eine Instanz von' DateInfoViewModel'? – dkozl

+0

@ dkozl: Sorry, habe diesen Teil vergessen. Ich habe meine Frage bearbeitet. – gartenriese

+1

Es beantwortet eine Frage, schafft aber eine andere. Was machst du mit 'view'? Sie erstellen es, legen seinen 'DataContext' fest, verwenden ihn danach aber nicht mehr. Sind Sie sicher, dass die Instanz, die Sie sehen, dieselbe Instanz ist, für die Sie 'DataContext' festgelegt haben? – dkozl

Antwort

1

Sie scheinen zwei Instanzen von DateInfoView zu haben. Eine, die Sie in XAML definieren und eine, die Sie in Code erstellen. Sie setzen DataContext des letzteren, aber verwenden Sie es dann nicht. Sie können es in einem der wenigen Möglichkeiten beheben

Lösung 1

DataContext ganzer Window einstellen, welche DataContext Wert übergeben wird bis zu Ihrem UserControl

public MainWindow() 
{ 
    InitializeComponent(); 

    Game.DateInfoModel = new DateInfoModel(); 
    this.DataContext = new DateInfoViewModel(Game.DateInfoModel); 
} 

aber wie Sie sagen, dass Sie anderen Kontext wollen für verschiedene Kontrollen

Lösung 2

Geben UserControl Namen in XAML

<xx:DateInfoView ... x:Name="myUserControl"/> 

und es im Code verwenden hinter

public MainWindow() 
{ 
    InitializeComponent(); 

    Game.DateInfoModel = new DateInfoModel(); 
    myUserControl.DataContext = new DateInfoViewModel(Game.DateInfoModel); 
} 

würde ich aber dritte Lösung vorschlagen, wo man größere Ansicht Modell zu erstellen, mit kleineren Ansicht Modelle als Eigenschaften, setzen Sie es als DataContext des gesamten Fensters und in XAML Bindung DataContext von bestimmten UserControl(s) zu Eigenschaften des größeren Ansichtsmodells. So muss man DataContext nur einmal setzen und es wird auf alle anderen Steuerelemente im Fenster übertragen.

1

ändern

view.DataContext = viewModel; 

zu

this.DataContext = viewModel; 

, wie Sie die Datacontext von Mainwindow setzen müssen, wenn die Usercontrol in diesem

befindet
+0

Das funktioniert, aber ich frage mich, wie ich in meinem MainWindow mehrere Ansichten mit jeweils eigenem Viewmodel implementieren würde. – gartenriese

+1

@gartenriese löst das Problem durch Zufall. Sie haben eine Instanz von "DateInfoView" in XAML und eine, die Sie in Code erstellen (die Sie nicht danach verwenden). Sie können 'DataContext' von' UserControl' genauso gut einstellen, aber es muss dieselbe Instanz sein, zum Beispiel indem Sie auf die Kontrolle über den Namen verweisen. – dkozl

+0

@dkozl: Ja, ich habe das gerade dank deines Kommentars herausgefunden. Wenn du eine Antwort postest, werde ich es gerne annehmen. – gartenriese