• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

WPF - Najprostsza aplikacja z wzorcem MVVM - prośba o pomoc

VPS Starter Arubacloud
+1 głos
1,788 wizyt
pytanie zadane 2 stycznia 2016 w C# przez Fergus Obywatel (1,010 p.)

Witam wszystkich,

Nie potrafię znaleźć najprostszego przykładu zastosowania wzorca MVVM w aplikacjach pisanych w WPF. Oczywiście są w sieci jakieś proste przykłady zastosowania tego wzorca, ale potrzebuję zrozumieć esencję działania takiej prostej aplikacji, najprostszy program - dzięki temu już powinienem poradzić sobie z bardziej skomplikowanymi programami pisanymi z zastosowaniem tego wzorca.

Tu http://www.fergerion.pl/ znajdują się screeny z mojego projektu.

Zrobiłem najprostszy jaki mi tylko przyszedł do głowy widok (w projekcie pojawia się on w folderze View), który ma na celu dodanie dwóch liczb: user wpisuje dwie liczby, klika na button "Wynik" i w zielonej kontrolce "label" pojawia się wynik dodawania.

W folderze View mamy więc plik z widokiem o nazwie: Calculator.xaml. Pozostaje dopisać klasy w folderach Model i ViewModel.

Czy możecie mi powiedzieć co w takim przypadku powinno pojawić się w plikach CalculatorModel.cs i CalculatorViewModel.cs ?

Oczywiście można by to wszystko obsłużyć w minutę w pliku Calculator.xaml.cs, czyli w tzw. code behind, ale nie o to chodzi, nie taka jest idea wzorca MVVM. Według MVVM plik Calculator.xaml.cs ma pozostać "czysty".

Będę bardzo wdzięczny za naprowadzenie mnie w tej kwestii. Czasem wystarczy kilka prostych podpowiedzi i są w stanie człowieka popchać do przodu z czymś, z czym męczy się sam.

 

Fergus

2 odpowiedzi

+1 głos
odpowiedź 3 stycznia 2016 przez adrian17 Ekspert (344,100 p.)
Czyli... w zasadzie nie wiesz nic o MVVM, a już stworzyłeś projekt :P

Przykładowy kompletny poradnik masz tu: http://www.codeproject.com/Articles/819294/WPF-MVVM-step-by-step-Basics-to-Advance-Level

I większą listę tu: http://stackoverflow.com/a/2034333/2468469
komentarz 3 stycznia 2016 przez Fergus Obywatel (1,010 p.)
Dzięki wielkie za te linki. Powalczę z tym. Zgadza się, w zasadzie nic nie wiem o MVVM, a jeśli wydawało mi się, że cokolwiek wiem to naprawdę niewiele i póki co ten stan nie pozwala mi na napisanie nawet najprostszej aplikacji z zastosowaniem tego wzorca. Czeka mnie ciężka przeprawa z tym.

Dzięki raz jeszcze. Idę z tym walczyć.

 

Fergus
komentarz 24 stycznia 2016 przez Fergus Obywatel (1,010 p.)

Cześć,

Ciąg dalszy mojej walki z WPV i MVVM - chyba prostszej aplikacji nie można wymyśleć - ma wyświetlić:

Samochód

Nazwę

Numer rejestracyjny

Nie wyświetla nazwy i numeru rejestracyjnego. Gdzie jest błąd? Poniżej wklejam kod plików: Samochod.cs, SamochodViewModel.cs, SamochodView.xaml i App.xaml:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Samochod.Model
{
    class Samochod
    {
        public string Nazwa { get; private set; }
        public int NumerRejestracyjny { get; private set; }

        public Samochod(string nazwa, int numerRej)
        {
            Nazwa = nazwa;
            NumerRejestracyjny = numerRej;
        }
    }
}

----------------------------------------


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Samochod.ViewModel
{

    using Model;
    using System.Collections.ObjectModel;

    class SamochodViewModel
    {
        public SamochodViewModel()
        {
            Samochod auto = new Samochod("VW", 777);
        }    
    }
}

--------------------------------------------

<UserControl x:Class="Samochod.View.SamochodView"
             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:view="clr-namespace:Samochod.View"
             xmlns:viewmodel="clr-namespace:Samochod.ViewModel"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">

    <UserControl.Resources>

        <viewmodel:SamochodViewModel x:Key="SamochodViewModel" />

        <DataTemplate x:Key="SamochodItemTemplate">
            <TextBlock>                
                <Run Text="{Binding Nazwa, Mode=OneWay}" />
                <Run Text="{Binding NumerRejestracyjny, Mode=OneWay}" />
            </TextBlock>
        </DataTemplate>
        
    </UserControl.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Border BorderThickness="2" BorderBrush="Blue" CornerRadius="6" Background="Black">
            <StackPanel Margin="20">

                <TextBlock Foreground="White" FontFamily="Segoe" FontSize="16px"
                           Text="Samochód" Margin="0,5,0,0" FontWeight="Bold"/>
                <TextBlock Foreground="White" FontFamily="Segoe" FontSize="20px"                                                
                           Text="{Binding Nazwa}" />
                <TextBlock Foreground="White" FontFamily="Segoe" FontSize="20px"
                           Text="{Binding NumerRejestracyjny}" />
            </StackPanel>
        </Border>
    </Grid>
</UserControl>

------------------------------------

<Application x:Class="Samochod.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="View/SamochodView.xaml">
    <Application.Resources>
         
    </Application.Resources>
</Application>

--------------------------------------

Będę bardzo wdzięczny za wszystkie podpowiedzi. Błąd jest pewnie banalny.

komentarz 24 stycznia 2016 przez adrian17 Ekspert (344,100 p.)
Na oko... zrobiłeś tylko auto jako zmienną lokalną w konstruktorze, a pewnie powinien być właściwością klasy.
komentarz 24 stycznia 2016 przez Fergus Obywatel (1,010 p.)

Dzięki. Jak w takim razie powinien wyglądać kod? Jak z obiektu zrobić właściwość klasy? Wiem, zadaję pytania początkującego, ale jestem właśnie początkującym. Na razie zrobiłem to jak poniżej, dane są wyświetlane, ale nie zadowala mnie to, bo wolałbym stworzyć obiekt o właściwościach: Nazwa i Numer Rejestracyjny i żeby to one były wyświetlane.

namespace Samochod.ViewModel
{

    using Model;
    using System.Collections.ObjectModel;

    class SamochodViewModel
    {        
        public string Nazwa { get; set; }
        public int NumerRejestracyjny { get; set; }

        public SamochodViewModel()
        {
            Nazwa = "VW";
            NumerRejestracyjny = 8888;
            //Samochod auto = new Samochod("VW", 8888);
        }     
    }
}

 

komentarz 24 stycznia 2016 przez adrian17 Ekspert (344,100 p.)

...znasz C#?

public Samochod Auto {get; set;}

 

komentarz 24 stycznia 2016 przez Fergus Obywatel (1,010 p.)

Dzięki za podpowiedź. Uczę się C#. Kod klasy wygląda teraz jak poniżej. Nadal jednak nie działa. Nie wiem co i gdzie mogłem zrobić nie tak. Aplikacja jest banalna, ma tylko wyświetlić dwie właściwości obiektu.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Samochod.ViewModel
{
    using Model;
    using System.Collections.ObjectModel;

    class SamochodViewModel
    {        
        public string Nazwa { get; set; }
        public int NumerRejestracyjny { get; set; }
        public Samochod auto { get; set; }

        public SamochodViewModel()
        {
            //Nazwa = "VW";
            //NumerRejestracyjny = 8888;
            Samochod auto = new Samochod("VW", 8888);
        }
    }
}

 

komentarz 25 stycznia 2016 przez Fergus Obywatel (1,010 p.)

Dzięki za pomoc i przede wszystkim za cierpliwość. Poprawiłem kod. Wrzucam, może przyda się potomnym, którzy tak jak ja raczkują w C# i MVVM. Kod zmieniłem w plikach SamochodViewModel i SamochodView.xaml. To chyba najprostsza aplikacja z wykorzystaniem wzorca MVVM - wyświetla dwie właściwości obiektu. Ucząc się na takich banałach można powoli przechodzić do trudniejszych programów, krok po kroku.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Samochod.ViewModel
{
    using Model;
    using System.Collections.ObjectModel;

    class SamochodViewModel
    {        
        public string Nazwa { get; set; }
        public int NumerRejestracyjny { get; set; }
        public Samochod Auto { get; set; }

        public SamochodViewModel()
        {
            //Nazwa = "VW";
            //NumerRejestracyjny = 8888;
            Auto = new Samochod("VW", 8888);
        }
    }
}

---------------------------------------

<UserControl x:Class="Samochod.View.SamochodView"
             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:view="clr-namespace:Samochod.View"
             xmlns:viewmodel="clr-namespace:Samochod.ViewModel"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">

    <UserControl.Resources>
        <viewmodel:SamochodViewModel x:Key="SamochodViewModel" />
        <DataTemplate x:Key="SamochodItemTemplate">
            <TextBlock>                
                <Run Text="{Binding Nazwa, Mode=OneWay}" />
                <Run Text="{Binding NumerRejestracyjny, Mode=OneWay}" />
            </TextBlock>
        </DataTemplate>
    </UserControl.Resources>

    <Grid>
     
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Border BorderThickness="2" BorderBrush="Blue" CornerRadius="6" Background="Crimson">
            <StackPanel Margin="20" DataContext="{StaticResource ResourceKey=SamochodViewModel}">
                <TextBlock Foreground="White" FontFamily="Segoe" FontSize="16px"
                           Text="Samochód" Margin="0,5,0,0" FontWeight="Bold"/>
                <TextBlock Foreground="White" FontFamily="Segoe" FontSize="20px"                                                
                           Text="{Binding Auto.Nazwa}" />
                <TextBlock Foreground="White" FontFamily="Segoe" FontSize="20px"
                           Text="{Binding Auto.NumerRejestracyjny}" />
            </StackPanel>
        </Border>
    </Grid>
</UserControl>

 

komentarz 25 stycznia 2016 przez adrian17 Ekspert (344,100 p.)
Dziwnie wygląda ten przykład: 1. w ViewModelu pola Nazwa i NumerRejestracyjny nie mają sensu i nie wydają się być używane, 2. nie widzę żebyś gdziekolwiek używał ten ItemTemplate, po co Ci on?
komentarz 26 stycznia 2016 przez Fergus Obywatel (1,010 p.)

Zgadza się. Zakomentowałem fragmenty kodu, które wskazałeś i program nadal działa poprawnie. Obiekt "Auto" właściwości pobiera z modelu. Natomiast do SamochodView właściwości pobierane są z DataContext="{StaticResource ResourceKey=SamochodViewModel}" oraz z Text="{Binding Auto.Nazwa}" i Text="{Binding Auto.NumerRejestracyjny}".

Dla porządku wrzucam raz jeszcze kod obu plików z zakomentowanymi fragmentami, które nie są potrzebne. Dzięki wielkie za zwrócenie uwagi.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Samochod.ViewModel
{
    using Model;
    using System.Collections.ObjectModel;

    class SamochodViewModel
    {        
        //public string Nazwa { get; set; }
        //public int NumerRejestracyjny { get; set; }
        public Samochod Auto { get; set; }

        public SamochodViewModel()
        {
            //Nazwa = "VW";
            //NumerRejestracyjny = 8888;
            Auto = new Samochod("VW", 8888);
        }
    }
}

------------------------------------------

<UserControl x:Class="Samochod.View.SamochodView"
             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:view="clr-namespace:Samochod.View"
             xmlns:viewmodel="clr-namespace:Samochod.ViewModel"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">

    <UserControl.Resources>
        <viewmodel:SamochodViewModel x:Key="SamochodViewModel" />
        <!--<DataTemplate x:Key="SamochodItemTemplate">
            <TextBlock>                
                <Run Text="{Binding Nazwa, Mode=OneWay}" />
                <Run Text="{Binding NumerRejestracyjny, Mode=OneWay}" />
            </TextBlock>
        </DataTemplate>-->
    </UserControl.Resources>

    <Grid>
     
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Border BorderThickness="2" BorderBrush="Blue" CornerRadius="6" Background="Crimson">
            <StackPanel Margin="20" DataContext="{StaticResource ResourceKey=SamochodViewModel}">
                <TextBlock Foreground="White" FontFamily="Segoe" FontSize="16px"
                           Text="Samochód" Margin="0,5,0,0" FontWeight="Bold"/>
                <TextBlock Foreground="White" FontFamily="Segoe" FontSize="20px"                                                
                           Text="{Binding Auto.Nazwa}" />
                <TextBlock Foreground="White" FontFamily="Segoe" FontSize="20px"
                           Text="{Binding Auto.NumerRejestracyjny}" />
            </StackPanel>
        </Border>
    </Grid>
</UserControl>

 

0 głosów
odpowiedź 6 marca 2017 przez PejtaM Użytkownik (550 p.)

Wzorzec MVVM posiada 3 warstwy: 

  • Warstwa Model: Czyli klasy które stworzymy wraz z odpowiednią logiką biznesową
  • Warstwa View: czyli XAML
  • Warstwa ViewModel: czyli warstwa (klasa dziedzicząca z ViewModelBase), która umożliwia "komunukację" poprzez Propertiesy posiadające OnPropertyChange() / RaisePropertyChange() pomiędzy widokiem a modelem.

Generalnie MVVM opiera się na Bindowaniu elementów, także warto o tym poczytać trochę więcej we własnym zakresie :)

Powiedzmy, że masz w XAML dwa TextBoxy + Button do wykonania akcji:

XAML:
<TextBox Name="FirstName" Text={Binding FistNameProp}  />
<TextBox Name="LastName" Text={Binding LastNameProp}  />
<Button Name="GetPerson" Content="Save person" Command="{Binding GetPerson}" />}"

MainViewModel: ViewModelBase

public ICommand GetPerson { get; private set; }
+ w konstruktorze MainVM inicjalizujesz ICommand
słówko kluczowe new RelayCommand(metoda, która będzie się aktywowała po kliknięciu przycisku);

private string _firstNameProp;
public string FirstNameProp
{
    get { return _firstNameProp; }
    set 
    {
        _firstNameProp = value;
        RaisePropertyChange("FirstNameProp");
    }
}

private string _lastNameProp;
public string LastNameProp
{
    get { return _lastNameProp; }
    set 
    {
        _lastNameProp= value;
        RaisePropertyChange("LastNameProp");
    }
}


Następnie tworzysz klasę Person ze zmiennymi/właściwościami (string, string) i metodzie ICommanda tworzysz obiekt 
klasy Person i w konstruktorze przekazujesz zmienne przychodzące z Bindingu.

I masz już obiekt klasy Person z FName i LName pochodzącymi z UI. Pozniej możesz to wykorzystać jak chcesz 
(przykładowo jakaś lista itp.)

Nie jestem jakimś wyjadaczem ale mam nadzieje, że pomogłem.

Podobne pytania

0 głosów
3 odpowiedzi 704 wizyt
pytanie zadane 21 kwietnia 2020 w C# przez eugi Użytkownik (570 p.)
0 głosów
1 odpowiedź 524 wizyt
pytanie zadane 19 maja 2019 w C# przez DrajzleR Obywatel (1,380 p.)
0 głosów
1 odpowiedź 357 wizyt
pytanie zadane 15 maja 2019 w C# przez DrajzleR Obywatel (1,380 p.)

92,453 zapytań

141,262 odpowiedzi

319,088 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...