I have a WPF app that loads a grid table through a db query. This works as expected. I want to add a tile layout, something like this. This image represents one row.
The two different views are a separate page that load in the main window. My first problem was setting the data context on each page. I solved that by setting the data context in the main window. There are two menu buttons that will change between the views. I want to be able to display the same data when I switch pages, without making a new call to the db.
public MainWindow()
{
DataContext = (new MovieViewModel()).GetMoviesAsync().Result;
InitializeComponent();
MovieList.DataContext = DataContext;
MainFrame.Content = MovieList;
}
private void ListView_Click(object sender, RoutedEventArgs e)
{
MovieList.DataContext = DataContext;
MainFrame.Content = MovieList;
}
private void TileView_Click(object sender, RoutedEventArgs e)
{
MovieGrid.DataContext = DataContext;
MainFrame.Content = MovieGrid;
}
The grid still populates but the tile only lists one record (understandably). I need it to dynamically build the rows based on the data context. Here is what I have in the "tile" xaml file.
<Page x:Class="MovieManager.Pages.MovieGrid"
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:local="clr-namespace:MovieManager.ViewModels"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="MovieGrid">
<Page.DataContext>
<local:MovieViewModel/>
</Page.DataContext>
<Grid
Name="MovieTileLayout" ShowGridLines="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBox Name="TxtMovieName" Text="{Binding Title}" Grid.Column="0" Grid.Row="0"/>
<TextBox Name="TxtMovieYear" Text="{Binding ReleaseDate}" Grid.Column="1" Grid.Row="0"/>
</Grid>
</Page>
If it will help, here is my view model
using MovieManager.Models;
using MovieManager.Repository;
using System.ComponentModel;
namespace MovieManager.ViewModels
{
public class MovieViewModel : INotifyPropertyChanged
{
private int movieId { get; set; }
private int groupId { get; set; }
private string title { get; set; }
private string description { get; set; }
private string[] tags { get; set; }
private string coverImage { get; set; }
private DateOnly releaseDate { get; set; }
private string omdb { get; set; }
private string groupName { get; set; }
public int MovieId
{
get
{
return movieId;
}
set
{
if (movieId != value)
{
movieId = value;
RaisePropertyChanged("MovieId");
}
}
}
public int GroupId
{
get
{
return groupId;
}
set
{
if(groupId != value)
{
groupId = value;
RaisePropertyChanged("GroupId");
}
}
}
public string Title {
get
{
return title;
}
set
{
if (title != value)
{
title = value;
RaisePropertyChanged("Title");
}
}
}
public string Description {
get
{
return description;
}
set {
if (description != value)
{
description = value;
RaisePropertyChanged("Description");
}
}
}
public string[] Tags {
get
{
return tags;
}
set
{
if (tags != value)
{
tags = value;
RaisePropertyChanged("Tags");
}
}
}
public string CoverImage {
get
{
return coverImage;
}
set
{
if(coverImage != value)
{
coverImage = value;
RaisePropertyChanged("CoverImage");
}
}
}
public DateOnly ReleaseDate {
get
{
return releaseDate;
}
set
{
if(releaseDate != value)
{
releaseDate = value;
RaisePropertyChanged("ReleaseDate");
}
}
}
public string OMDB {
get
{
return omdb;
}
set
{
if(OMDB != value)
{
omdb = value;
RaisePropertyChanged("OMDB");
}
}
}
public string GroupName {
get
{
return groupName;
}
set
{
if(groupName != value)
{
groupName = value;
RaisePropertyChanged("GroupName");
}
} }
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
public async Task<List<Movie>> GetMoviesAsync()
{
var repository = new MovieRepository();
return await repository.GetAllMoviesAsync();
}
}
}
<local:MovieViewModel/>
specified in the Data Context. This means that the XAML is built for aMovieViewModel
instance, notMovie
instance. The bindings in the XAML also specify paths to the properties of theMovieViewModel
instance. At the same time, in Code Behind MainVindow, you set the result of theMovieViewModel.GetAllMoviesAsync
method in the Window Data Context. This method returns a list ofMovie
. And this list replaces theMovieViewModel
created in XAML. There is no hint anywhere in your code how, where from, you get ONEMovie
instance.