2017-09-18 2 views
0

So lerne ich WPF, indem ich ein Yatzee-Spiel mache, und ich komme irgendwo hin. Aber jetzt kann ich nicht verstehen, warum ich meinen "aktuellen Roll" -Zähler nicht in der Ansicht aktualisieren werde. Ich habe die Würfel gemacht, und der Rollwürfel-Knopf gibt meinen Würfeln neue Werte - und dies wird in der Ansicht aktualisiert. Aber meine "Current roll" Variable wird nicht. Das habe ich bisher gemacht.Ich kann meinen Wert nicht mit INotifyPropertyChanged aktualisieren

// CurrentRoll.cs 
    public class CurrentRoll : INotifyPropertyChanged 
{ 
    public int _roll; 

    public int Roll 
    { 
     get { return _roll; } 
     set 
     { 
      if (value != _roll) 
      { 
      _roll = value; 
      OnPropertyChanged("Roll"); 
      } 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected void OnPropertyChanged(string name) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(name)); 
     } 
    } 
} 

Dann ist dies meine DiceModelView. Wenn ich den "Roll Dices" -Button drücke, bekomme ich neue Werte auf allen meinen Würfeln, solange sie nicht markiert sind. Ich inkrementiere auch die Variable _currentRoll und erlaube nur neue Würfe, solange _currentRoll immer noch kleiner als 3 ist. Diese Logik funktioniert, die Variable funktioniert, aber ihre Darstellung in der Ansicht funktioniert nicht. Ich habe auch seinen Anfangswert auf andere Werte geändert, nur um zu sehen, dass meine Bindung funktioniert, und das tut es auch.

public class DiceModelView : INotifyPropertyChanged 
{ 
    Die _die; 
    public CurrentRoll _currentRoll; 

    public event PropertyChangedEventHandler PropertyChanged; 

    public ObservableCollection<Die> myDices { get; set; } 
    public ICommand RollCommand { get; set; } 

    public DiceModelView() 
    { 
     myDices = new ObservableCollection<Die>() 
     { 
      new Die { Id = 0, Roll = 0, Checked = false }, 
      new Die { Id = 1, Roll = 0, Checked = false }, 
      new Die { Id = 2, Roll = 0, Checked = false }, 
      new Die { Id = 3, Roll = 0, Checked = false }, 
      new Die { Id = 4, Roll = 0, Checked = false } 
     }; 
     _currentRoll = new CurrentRoll(); 
     _currentRoll._roll = 0; 
     RollCommand = new Command (executeMethod, canexecuteMethod); 
    } 

    public bool canexecuteMethod(object parameter) 
    { 
     return true; 
    } 

    private void executeMethod(object parameter) 
    { 
     var r = new Random(); 
     if (_currentRoll._roll < 3) 
     { 
      foreach (Die d in myDices) 
      { 
       if (d.Checked == false) 
       { 
        d.Roll = r.Next(1, 7); 
       } 
      } 
     } 
     _currentRoll._roll++; 
    } 

    private void NotifyPropertyChanged(String propertyName = "") 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    public Die die 
    { 
     get { return _die; } 
     set { _die = value; } 
    } 

    public CurrentRoll currentRoll 
    { 
     get { return _currentRoll; } 
     set { _currentRoll = value; 
      NotifyPropertyChanged("currentRoll"); 
     } 
    } 

How my application is now, in this example I set _currentRoll._roll to 111 just to be sure that it works. I've not rolled any dices as the aforementioned value is more than 3.

Schließlich ist dies der XAML-Code, den ich verwenden:

<Window.DataContext> 
    <local:DiceModelView/> 
</Window.DataContext> 
<StackPanel> 
    <TextBlock Text="{Binding currentRoll.Roll, UpdateSourceTrigger=PropertyChanged}"/> 
    <ListView x:Name="DiceView" ItemsSource="{Binding myDices}" Width="500" HorizontalContentAlignment="Center" > 
     <ListView.ItemTemplate> 
      <DataTemplate > 
       <CheckBox Content="{Binding Roll}" IsChecked="{Binding Checked}"/> 
      </DataTemplate> 
     </ListView.ItemTemplate> 
    </ListView> 
    <Button Content="Roll the dices!" Command="{Binding RollCommand}"/> 
</StackPanel> 
</Window> 
+1

Nicht verwandt: Sie haben ein * public * -Feld und eine * public * -Eigenschaft, die von diesem Feld unterstützt wird. Und Sie greifen direkt über die Eigenschaft auf das Feld * und * zu. Dies * wird * früher oder später in deinem Gesicht nach hinten losgehen. – Fildor

+1

@Fildor: Warum "nicht verwandt"? Das ist genau das Problem hier :) –

+0

@DanielHilgarth Oh, ich habe nicht erwartet, dass es tatsächlich das Problem vollständig lösen wird. – Fildor

Antwort

5

Sie müssen die Roll Eigenschaft aktualisieren, nicht das _role Feld.

_roll sollte sowieso privat sein.

Denken Sie einfach darüber nach: Sie erhöhen das Ereignis "Eigenschaft geändert" im Eigenschaftensetter, sodass dies nur ausgeführt wird, wenn Sie den Wert der Eigenschaft festlegen.

+0

Das hat den Trick! Vielen Dank! Die Tatsache, dass die _rolle öffentlich war, war die Ursache, intellisens sagte mir immer, ich solle mit _currentRoll._roll anstatt _currentRoll.Roll gehen. – Tom

+1

@Tom: Ihr Kommentar macht keinen Sinn für mich. Weder 'Roll' noch' _roll' waren privat in deiner Klasse, zumindest nicht von dem Code, den du uns gegeben hast. –

+0

Typo. Ich meinte öffentlich, Entschuldigung. Es privat zu machen, machte den Trick. – Tom

Verwandte Themen