2016-05-05 10 views
0

So habe ich die Idee, mehrere Schaltflächen zu einem Raster hinzufügen, dann ordnen sie, und die Anzahl der Schaltflächen hinzugefügt, um eine Nummer, die ich eingeben. Alles funktioniert gut, bis ich versuche, es unter MVVM arbeiten zu lassen.Zugriff auf Grid.Children.Add in MVVM (WPF)

Code, der in der MainWindow.xaml.cs funktioniert:

private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     int i = 0, j = 0; 
     Brush[] bs = { Brushes.BurlyWood, Brushes.Honeydew }; 

     for (i = 0; i < 3; i++) 
     { 
      for (j = 0; j < 3; j++) 
      { 
       Button btn = new Button(); 
       btn.Height = 50; 
       btn.Width=50; 
       btn.SetValue(Grid.RowProperty, i); 
       btn.SetValue(Grid.ColumnProperty, j); 
       if ((i + j) % 2 == 0) 
       { 
        btn.Background=bs[0]; 
       } 
       else btn.Background = bs[1]; 

       GameGrid.Children.Add(btn); 
      } 
     } 
    } 

Also im Grunde, drücke ich auf einen Knopf und es fügt 3x3 Tasten, farbige schön und angemessen verteilt. Aber dann komme ich zum MVVM:

private void ButtonClickCommand() 
    { 
     RowCount = GridNumber; 
     ColumnCount=GridNumber; 
     int i = 0, j = 0; 

     Brush[] bs = { Brushes.BurlyWood, Brushes.Honeydew }; 

     for (i = 0; i < GridNumber; i++) 
     { 
      for (j = 0; j < GridNumber; j++) 
      { 
       Button btn = new Button(); 
       btn.Height = 50; 
       btn.Width = 50; 
       // btn.Command = StartCommand; Ill add that later 
       btn.SetValue(Grid.RowProperty, i); 
       btn.SetValue(Grid.ColumnProperty, j); 
       if ((i + j) % 2 == 0) 
       { 
        btn.Background = bs[0]; 
       } 
       else btn.Background = bs[1]; 

       somebuttonlist.Add(btn); 
      } 
     } 

    } 

Hier habe ich eine Liste der Tasten, die das neu erstellte Schaltflächen annehmen sollen, übertragen sie dann an das Netz. Code der Schaltfläche Liste:

private List<Button> _bslist = new List<Button>(); 
    public List<Button> somebuttonlist 
    { 
     get 
     { 
      return _bslist; 
     } 
     set 
     { 
      _bslist = value; 
      NotifyPropertyChanged(); 

     } 
    } 

Und XAML-Code:

<ItemsControl ItemsSource="{Binding somebuttonlist}"> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <Grid Name="GameGrid" Visibility="{Binding GameVis}" 
       vm:GridHelpers.RowCount="{Binding RowCount}" 
       vm:GridHelpers.ColumnCount="{Binding ColumnCount}"> 
       </Grid> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
    </ItemsControl> 

nicht alle Bindungen Stört es, sie richtig funktionieren, wenn ich das nicht-MVVM-Format verwenden. Wie kann ich den Arbeitscode ordnungsgemäß in das View Model übertragen? Gibt es eine Möglichkeit, die Kinder entsprechend zu erreichen?

Antwort

0

Offenbar sind Sie an eine List gebunden, die nicht benachrichtigt, wenn neue Datensätze eingefügt oder ein Datensatz gelöscht wird. Die NotifyPropertyChanged(), die Sie nur gestartet haben, wenn der Verweis auf diese Liste geändert wird, also beispielsweise auf new List() oder einen anderen List. Versuchen Sie stattdessen, es in eine ObservableCollection zu ändern, die eine event sendet, wenn die Anzahl der Datensätze in der Sammlung geändert wird.

+0

Nun, das hat funktioniert: D Danke, ich muss noch viel lernen – NamelessCoder

0

Dies ist nicht der richtige Weg, Dinge mit MVVM zu tun. Was Sie jetzt versuchen, ist visueller Code in Ihr ViewModel zu ziehen. Im Idealfall sollten ViewModels in einem separaten Projekt ohne Verweise auf visuelle Elemente bleiben. Auf diese Weise führt die Referenzierung Button zu einem fehlerhaften Code, es sei denn, Sie fügen eine Referenz für System.Windows.Controls hinzu und dies erinnert Sie daran, dass Sie die Dinge falsch machen.

Was Sie versuchen, ist in der reinen MVVM-Art machbar, aber wird in viel mehr Code resultieren, der auch zu Ihnen gewunden wird, wenn Sie MVVM noch nicht verstanden haben. Beachten Sie auch, dass es im wirklichen Leben akzeptabel ist, einen Code für komplizierte Szenarien zu haben. Dazu erstellen Sie einfach ein benutzerdefiniertes Steuerelement, um den gesamten Code hinter der Logik zu kapseln.

Die nette Lösung in Ihrem Fall kann ein benutzerdefiniertes Steuerelement sein, das Grid und Logik einkapselt, um es mit Schaltflächen zu füllen. Sie fügen auch Abhängigkeitseigenschaften für Zeilen und Spalten hinzu, sodass Sie in XAML an sie binden können und einen Befehl definieren können, der beim Klicken auf die Schaltfläche aufgerufen wird. Dies kann ein gutes Beispiel sein: How to create bindable commands in Custom control?