2016-05-06 7 views
2

ich so viele Stunden, dieses Problem zu lösen versuchen:wpf C# verbindlicher Datenstring mit Eigenschaft von Viewmodel-Objekt setzen

I Benutzer individuelle Steuerung des Netzes NewMazeGrid genannt habe, und ich will es als Kontrolle verwenden, in MainWindow. MainWindow enthält MazeViewModel (mazeVM-Mitglied).

Ich versuche, die Werte des Rasters festzulegen, wenn sich die Eigenschaft MazeViewModel:MySingleplay ändert. (. Ich bin die INotifyPropertyChanged dafür verwenden, und es funktioniert völlig in Ordnung, ich denke, das Problem ist in der endgültigen Bindung) Der Code:

Dies ist die Eigenschaft MazeViewModel:MySingleplay Getter:

public string MySingleplay 
     { 
      get 
      { 
       if (myModel.MySingleplay == null) 
       { 
        return ""; 
       } else 
       { 
        return myModel.MySingleplay.ToString();//works perfect 
       } 
      } 
     } 

ist dies die NewMazeGrid.xaml.cs:

namespace VisualClient.View.controls 
{ 
    public partial class NewMazeGrid : UserControl 
    { 
     private MazePresentation myMaze; 
     private string order; //dont really use it 

     //Register Dependency Property 

     public static readonly DependencyProperty orderDependency = 
      DependencyProperty.Register("Order", typeof(string), typeof(NewMazeGrid)); 

     public NewMazeGrid() 
     { 
      myMaze = new MazePresentation(); 
      InitializeComponent(); 
      DataContext = this; 
      lst.ItemsSource = myMaze.MazePuzzleLists; 
     } 

     public string Order 
     { 
      get 
      { 
       return (string)GetValue(orderDependency); 
      } 
      set 
      { 
       SetValue(orderDependency, value); 
       myMaze.setPresentation(value); //(parsing string into matrix) 
      } 
     } 
    } 
} 

dies die MainWindow.xaml.cs:

public partial class MainWindow : Window 
    { 
     private MazeViewModel mazeVM; 

     public MainWindow() 
     { 
      InitializeComponent(); 

      mazeVM = new MazeViewModel(new ClientMazeModel(new TCPClientConnection())); 
      DataContext = mazeVM; 

      mazeVM.connectToServer(); 
     } 

     private void bu_Click(object sender, RoutedEventArgs e) 
     { 
      bool isC = mazeVM.isConnected(); 
      mazeVM.openSingleplayGame("NewMaze");//works perfect 
     } 

ist dies die MainWindow.xaml:

<Window x:Class="VisualClient.View.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:Controls ="clr-namespace:VisualClient.View.controls" 
     xmlns:vm ="clr-namespace:VisualClient.ViewModel" 
     xmlns:local="clr-namespace:VisualClient.View" 

     mc:Ignorable="d" 
     Title="Main Window" Height="350" Width="525" MinWidth="900" MinHeight="600"> 
    <WrapPanel > 
     <Button Name ="bu" Content="Click_Me" Click="bu_Click"/> 
     <Grid Name="myGrid"> 
      <Controls:NewMazeGrid Order="{Binding MySingleplay, UpdateSourceTrigger=PropertyChanged}"/> 
     </Grid> 
    </WrapPanel> 
</Window> 

ich diesen Fehler an der Bindelinie: Wert nicht null sein kann.

Zusammengefasst: Es das Fenster in der Ctor fein initialisieren, aber wenn die Eigenschaft ändert es nicht in die Order-Eigenschaft Setter bekommen. deshalb ändert sich mein Raster nie.

Was sollte die richtige Syntax für die Bindung in diesem Fall sein? Wie binde ich es an die richtige Eigenschaft?

Folders hierarchy explorer

+0

Nicht sicher über die Bindungs ​​Fehler aber dafür, warum Ihr Setter nicht Look genannt wird [hier] (http: //stackoverflow.com/a/3836123/1454658) –

+0

Danke! kommt aber immer noch nicht mal in den MySingleplay property getter – OfKo

Antwort

0

WPF kann die CLR-Wrapper einer Abhängigkeitseigenschaft nicht nennen, aber nur direkt aufrufen, um die GetValue und SetValue Methoden des zugrunde liegenden DependencyObject. Aus diesem Grund sollte es außer den GetValue- und SetValue-Aufrufen keine Logik geben.

Dies ist in XAML Loading and Dependency Properties erklärt:

Da die aktuelle WPF Implementierung des XAML-Prozessor Verhalten für Eigenschaftseinstellung vollständig die Wrapper umgeht, sollten Sie nicht in die Set-Definitionen der Wrapper eine zusätzliche Logik setzen für Ihre benutzerdefinierte Abhängigkeitseigenschaft. Wenn Sie eine solche Logik in die Definition setzen, wird die Logik nicht ausgeführt, wenn die Eigenschaft in XAML und nicht im Code festgelegt ist.

In ähnlicher Weise verwenden andere Aspekte des XAML-Prozessors, die Eigenschaft Werte von XAML-Verarbeitung erhalten, auch GetValue lieber als Wrapper verwenden.Daher sollten Sie in der get-Definition über den GetValue-Aufruf hinaus auch keine zusätzliche Implementierung vermeiden.


Um über Eigenschaftswert ändert benachrichtigt, können Sie eine PropertyChangedCallback von Immobilien Metadaten registrieren. Beachten Sie auch, dass es eine Namenskonvention für DependencyProperty Felder gibt. Sie sollte OrderProperty genannt werden:

public static readonly DependencyProperty OrderProperty = 
    DependencyProperty.Register(
     "Order", typeof(string), typeof(NewMazeGrid), 
     new PropertyMetadata(OnOrderChanged)); 

public string Order 
{ 
    get { return (string)GetValue(OrderProperty); } 
    set { SetValue(OrderProperty, value); } 
}   

private static void OnOrderChanged(
    DependencyObject obj, DependencyPropertyChangedEventArgs e) 
{ 
    ((NewMazeGrid)obj).myMaze.setPresentation((string)e.NewValue); 
} 

Abgesehen davon, Sie nicht

DataContext = this; 

im Konstruktor von NewMazeGrid einstellen müssen. Dies verhindert effektiv das Erben des DataContext vom übergeordneten Fenster, so dass {Binding MySingleplay} nicht funktioniert. Außer unter besonderen Umständen sollten Sie nie explizit den DataContext eines UserControl festlegen.

Also, die Datacontext Zuordnung aus dem Konstruktor entfernen:

public NewMazeGrid() 
{ 
    myMaze = new MazePresentation(); 
    InitializeComponent(); 
    lst.ItemsSource = myMaze.MazePuzzleLists; 
} 

Das heißt, es gibt auch keine Notwendigkeit Bindung UpdateSourceTrigger=PropertyChanged auf einer Einbahn einzustellen. Es hat nur eine Wirkung in zwei-Wege (oder Einweg-Source) Bindungen:

<Controls:NewMazeGrid Order="{Binding MySingleplay}"/> 
+0

Danke für deinen Kommentar! Ich habe die _OnOrderChanged_ Funktion hinzugefügt, aber sie kommt immer noch nicht in den _MySingleplay Getter_, wenn sie Änderungen meldet. – OfKo

+0

Siehe die bearbeitete Antwort. – Clemens

+0

DANKE! jetzt kommt es in die Eigenschaften und ändert die Listen von myGrid. aber immer noch die Änderungen nicht auf dem Bildschirm angezeigt. Ich frage mich, ob das Entfernen von 'DataContext = this' das Problem sein kann? Ich benutzte diesen Code zum Anzeigen der Listen zu einem Label-Gitter: [link] (http://stackoverflow.com/a/276868) – OfKo

Verwandte Themen