WPF + MVVM - problem

0

Witam
Ucze się programować w C# i postanowiłem zrobić sobie małą aplikacje w WPF + MVVM i mam problem, z którym od dłuższego czasu się męczę ( pewnie jakaś głupota lub coś wynikające z mojej niewiedzy...) W widoku nic mi się nie wyświetla, po naciśnięciu przycisku nic się nie dzieje. Bardzo prosiłbym o sprawdzenie kodu. Wstawiam tylko fragmenty kodu, który sprawia mi trudność.

Model

 namespace Tabu.Model
{
    public class Team
    {
        public bool IsTeamActive { get;  set; }
        public int TeamPoints { get;  set; }
        public int TeamMiss { get;  set; }
        public int TeamMistake { get;  set; }

    }
}

ViewModel

 namespace Tabu.ViewModel
{
    class TeamStatistic : INotifyPropertyChanged

    {

        public Team Team1 = new Team();

        public int TeamPoints
        {
            get { return TeamPoints; }
            set { TeamPoints = value; OnPropertyChanged("TeamPoints"); }
        }

        private void AddPoints()
        {
            Team1.TeamPoints++;
        }

        public event PropertyChangedEventHandler PropertyChanged;
        
        private void OnPropertyChanged(params string[] propsName)
        {
            if (PropertyChanged!=null)
            {
                foreach(string propName in propsName)
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }

    }
}

Widok - tylko elementy związane z problemem

 <Window x:Class="Tabu.Game"
        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:local="clr-namespace:Tabu"
        xmlns:vm="clr-namespace:Tabu.ViewModel"
        mc:Ignorable="d"
        Title="Game"  Height="600" Width="900" Background="Beige">
    <Window.DataContext>
        <vm:TeamStatistic />
    </Window.DataContext>

<Grid>

<Button x:Name="PointUp" Command="{Binding AddPoints }" Content="+" />
<Label x:Name="PointsTeam1_label" Content="{Binding Team1.TeamPoints}" />

</Grid>
4

Nie możesz od tak zbindować komendy przycisku do zwykłej metody. Powinieneś wystawić własność typu ICommand i ją zbindować jako komendę lecz wcześniej będziesz musiał utworzyć klasę implementującą interfejs ICommand.

Klasa RelayCommand:

using System;
using System.Windows.Input;

namespace _4programmersWPF
{
    public class RelayCommand : ICommand
    {
        private readonly Func<bool> canExecute;
        private readonly Action execute;

        public RelayCommand(Action execute)
            : this(execute, null) { }

        public RelayCommand(Action execute, Func<bool> canExecute)
        {
            if (execute == null) throw new ArgumentNullException("execute");
            this.execute = execute;
            this.canExecute = canExecute;
        }

        public event EventHandler CanExecuteChanged
        {
            add { if (this.canExecute != null) CommandManager.RequerySuggested += value; }
            remove { if (this.canExecute != null) CommandManager.RequerySuggested -= value; }
        }

        public Boolean CanExecute(object parameter) { return this.canExecute == null ? true : this.canExecute(); }
        public void Execute(object parameter) { this.execute(); }
    }
}

XAML:

<Window x:Class="_4programmersWPF.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:local="clr-namespace:_4programmersWPF"
        xmlns:vm="clr-namespace:_4programmersWPF"
        mc:Ignorable="d"
        Title="4prog test app"
        Name="Window" WindowStartupLocation="CenterScreen" SizeToContent="WidthAndHeight">
  <Window.DataContext>
    <vm:MainWindowVM/>
  </Window.DataContext>
  <StackPanel>
    <Label Content="{Binding HelloText, UpdateSourceTrigger=PropertyChanged}"
           FontSize="14"/>
    <Button Command="{Binding PressMe}"
          Content="Press me!" FontSize="14"/>
  </StackPanel>
</Window>

ViewModel:

using System.ComponentModel;
using System.Windows.Input;

namespace _4programmersWPF
{
    public class MainWindowVM : INotifyPropertyChanged
    {
        private string helloText;
        public string HelloText
        {
            get { return this.helloText; }
            set
            {
                this.helloText = value;
                this.OnPropertyChanged(nameof(this.HelloText));
            }
        }

        public ICommand PressMe
        {
            get { return new RelayCommand(() => this.HelloText = "Button pressed!"); }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string property)
        {
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
        }
    }
}

Złóż projekt, skompiluj i zadziała :)

3

Po pierwsze metoda AddPoints jest prywatna, więc nie jest widoczna w ogóle dla widoku, jest widoczna tylko wewnątrz ViewModelu. Po drugie bindujesz z właściwością przycisku o nazwie Command, jak sama nazwa wskazuje musisz zbindować z to z komendą, a nie zwykłą metodą. Musisz w klasie VM stworzyć właściwość o typie, który implementuje interfejs ICommand i z tą właściwością zbindować. Tu masz przykład jak to zrobić

1 użytkowników online, w tym zalogowanych: 0, gości: 1