Benutzer mit den meisten Antworten
Universal Windows 10 App MVVM Beispiel

Frage
-
Hallo
Ich arbeite gerade an einer Windows Store APP und möchte Sie nach dem MVVM Schema aufbauen. Leider funktioniert das aktualisieren der View nicht wenn sich Daten ändern.
Hier mal ein Beispiel code MainPagexaml Code.
Unter Page-Resources wurde ein Instanz für das Binding zur Verfügung gestellt.
Auf der View befindet sich nur ein Textblock und ein Button. Die Textblock Eigenschaft Visibility ist an einem String gebunden.
Auf Button klick soll der Textblock nun verschwinden.
<Page.Resources> <local:Person x:Key="Person"/> </Page.Resources> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <TextBlock Margin="50,50,126,50" Text="Test" Visibility="{ Binding Source={StaticResource Person},Path=PersonName,Mode=TwoWay}" Name="tb"></TextBlock> <Button HorizontalAlignment="Right" Content="klick" Background="Black" Height="100" Width="100" Click="Button_Click"></Button> </Grid> </Page>
In der Codebehind wurde ein Viewmodel zur Verfügung gestellt und ein Event für den Buttonklick.
Der Buttonklick verweist auf eine Methode im ViewModel Person
public sealed partial class MainPage : Page { Person viewModel = new Person(); public MainPage() { this.InitializeComponent(); DataContext = viewModel; } private void Button_Click(object sender, RoutedEventArgs e) { viewModel.Click(); } }
Hier nun das ViewModel.
public class Person : INotifyPropertyChanged { public string name = "test"; // Declare the event public event PropertyChangedEventHandler PropertyChanged; public Person() { } public Person(string value) { this.name = value; } public string PersonName { get { return name; } set { name = value; // Call OnPropertyChanged whenever the property is updated OnPropertyChanged("PersonName"); } } // Create the OnPropertyChanged method to raise the event protected void OnPropertyChanged(string name) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(name)); } } public void Click() { PersonName = "Collapsed"; } }
Das INotifyPropertyChanged Interface wurde Implementiert.
In der Click Methode wird PersonName ein neuer Wert zugewiesen.
Eigentlich müsste doch der Textblock verschwinden.
Was mach ich Falsch?
Ist die Vorgehensweise korrekt wie ich ein Event an das ViewModel weiterleite für MVVM?
Antworten
-
Hallo,
im XAML bindest du an die Resource Person, welche du in die Resources-Eigenschaft des Page-Elements gelegt hast. Im Codebehind nutzt du dagegen eine eigene Klasse. Ändere deinen Code so ab, dass du nur einmal Person initialisierst und verwendest.
<TextBlock Margin="50,50,126,50" Text="Test" Visibility="{ Binding PersonName, Mode=TwoWay}" Name="tb"></TextBlock>
PersonName wird gefunden, da im DataContext gesucht wird und es sich dabei um eine Instanz der Person-Klasse handelt.
Alternativ kannst du das Person-Objekt im XAML in DataContext ablegen.
Visibility zu binden erscheint mir wenig sinnvoll. Willst du nicht vielleicht eher die Text-Eigenschaft binden? Für Visibility solltest du außerdem den richtigen Enumerationstyp und keinen String nutzen. TwoWay macht in meinen Augen in keinem der Fälle Sinn, da beide Eigenschaften bei einem TextBlock (keine TextBox) nicht verändert werden.
Für richtiges MVVM solltest du übrigens Commands und keine Events nutzen.
Tom Lambert - .NET (C#) MVP
Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets- Als Antwort markiert NixVonMix Mittwoch, 3. Februar 2016 20:50
Alle Antworten
-
Hallo,
im XAML bindest du an die Resource Person, welche du in die Resources-Eigenschaft des Page-Elements gelegt hast. Im Codebehind nutzt du dagegen eine eigene Klasse. Ändere deinen Code so ab, dass du nur einmal Person initialisierst und verwendest.
<TextBlock Margin="50,50,126,50" Text="Test" Visibility="{ Binding PersonName, Mode=TwoWay}" Name="tb"></TextBlock>
PersonName wird gefunden, da im DataContext gesucht wird und es sich dabei um eine Instanz der Person-Klasse handelt.
Alternativ kannst du das Person-Objekt im XAML in DataContext ablegen.
Visibility zu binden erscheint mir wenig sinnvoll. Willst du nicht vielleicht eher die Text-Eigenschaft binden? Für Visibility solltest du außerdem den richtigen Enumerationstyp und keinen String nutzen. TwoWay macht in meinen Augen in keinem der Fälle Sinn, da beide Eigenschaften bei einem TextBlock (keine TextBox) nicht verändert werden.
Für richtiges MVVM solltest du übrigens Commands und keine Events nutzen.
Tom Lambert - .NET (C#) MVP
Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets- Als Antwort markiert NixVonMix Mittwoch, 3. Februar 2016 20:50
-
Danke für deine Hilfe.
Das Problem lag an den zwei Objekten.
Ich verwende die Visibility-Eigenschaft oft dazu um Steuerelemente(Button) bei Bedarf ein und auszublenden. Löst man das anders?
Kannst mir die Commands vielleicht Anhand diesem Beispiel zeigen?
-
Man verwendet schon die Visibility-Eigenschaft, dann aber mit der Visibility-Enumeration.
Commands sind ein doch schon etwas komplexeres Thema. Häufig verwendet man zusätzliche Frameworks wie MVVM Light. Ein kurzes Beispiel für den Einstieg dazu findest du hier. Wenn du weitere konkrete Fragen hast, kannst du natürlich jederzeit eine neue Frage stellen (in einem neuen Thread um die Übersichtlichkeit zu wahren).
Tom Lambert - .NET (C#) MVP
Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets -
Die Variante mit den Commands war sehr hilfreich
Ich bin nun leider auf ein neues Problem beim MVVM Pattern gestoßen.
Wenn ich im XAML ein DataContext anlege wird jedes mal eine neue Instanz erzeugt wenn ich auf die Seite navigiere. Kann ich das irgendwie verhindern?
Wenn ich aber auf mein ViewModel in der Codebehind Datei verweise kann ich zwar mit einem Singelton verhindern das nicht mehr als eine Instanz erzeugt wird, aber dadurch funktioniert das Databinding nicht mehr, auf Eigenschaft von der Klasse in meiner ViewMode-Klassel.
Text="{Binding routeInfo.startDateStringFormat}"
Außerdem funktioniert dann IntelliSense nicht mehr was die Arbeit erheblich erschwert.
Ist es möglich in Xaml einen Singelton zu machen? oder löst man das anders.
- Bearbeitet NixVonMix Donnerstag, 4. Februar 2016 03:33