initial load
This commit is contained in:
63
.gitattributes
vendored
Normal file
63
.gitattributes
vendored
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
###############################################################################
|
||||||
|
# Set default behavior to automatically normalize line endings.
|
||||||
|
###############################################################################
|
||||||
|
* text=auto
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Set default behavior for command prompt diff.
|
||||||
|
#
|
||||||
|
# This is need for earlier builds of msysgit that does not have it on by
|
||||||
|
# default for csharp files.
|
||||||
|
# Note: This is only used by command line
|
||||||
|
###############################################################################
|
||||||
|
#*.cs diff=csharp
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Set the merge driver for project and solution files
|
||||||
|
#
|
||||||
|
# Merging from the command prompt will add diff markers to the files if there
|
||||||
|
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||||
|
# the diff markers are never inserted). Diff markers may cause the following
|
||||||
|
# file extensions to fail to load in VS. An alternative would be to treat
|
||||||
|
# these files as binary and thus will always conflict and require user
|
||||||
|
# intervention with every merge. To do so, just uncomment the entries below
|
||||||
|
###############################################################################
|
||||||
|
#*.sln merge=binary
|
||||||
|
#*.csproj merge=binary
|
||||||
|
#*.vbproj merge=binary
|
||||||
|
#*.vcxproj merge=binary
|
||||||
|
#*.vcproj merge=binary
|
||||||
|
#*.dbproj merge=binary
|
||||||
|
#*.fsproj merge=binary
|
||||||
|
#*.lsproj merge=binary
|
||||||
|
#*.wixproj merge=binary
|
||||||
|
#*.modelproj merge=binary
|
||||||
|
#*.sqlproj merge=binary
|
||||||
|
#*.wwaproj merge=binary
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# behavior for image files
|
||||||
|
#
|
||||||
|
# image files are treated as binary by default.
|
||||||
|
###############################################################################
|
||||||
|
#*.jpg binary
|
||||||
|
#*.png binary
|
||||||
|
#*.gif binary
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# diff behavior for common document formats
|
||||||
|
#
|
||||||
|
# Convert binary document formats to text before diffing them. This feature
|
||||||
|
# is only available from the command line. Turn it on by uncommenting the
|
||||||
|
# entries below.
|
||||||
|
###############################################################################
|
||||||
|
#*.doc diff=astextplain
|
||||||
|
#*.DOC diff=astextplain
|
||||||
|
#*.docx diff=astextplain
|
||||||
|
#*.DOCX diff=astextplain
|
||||||
|
#*.dot diff=astextplain
|
||||||
|
#*.DOT diff=astextplain
|
||||||
|
#*.pdf diff=astextplain
|
||||||
|
#*.PDF diff=astextplain
|
||||||
|
#*.rtf diff=astextplain
|
||||||
|
#*.RTF diff=astextplain
|
||||||
363
.gitignore
vendored
Normal file
363
.gitignore
vendored
Normal file
@ -0,0 +1,363 @@
|
|||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.rsuser
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Mono auto generated files
|
||||||
|
mono_crash.*
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Ww][Ii][Nn]32/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Oo]ut/
|
||||||
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
|
||||||
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# Visual Studio 2017 auto generated files
|
||||||
|
Generated\ Files/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUnit
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
nunit-*.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
# ASP.NET Scaffolding
|
||||||
|
ScaffoldingReadMe.txt
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_h.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.iobj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Coverlet is a free, cross platform Code Coverage Tool
|
||||||
|
coverage*.json
|
||||||
|
coverage*.xml
|
||||||
|
coverage*.info
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# NuGet Symbol Packages
|
||||||
|
*.snupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
*.appxbundle
|
||||||
|
*.appxupload
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
*.rptproj.bak
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
*- [Bb]ackup.rdl
|
||||||
|
*- [Bb]ackup ([0-9]).rdl
|
||||||
|
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# CodeRush personal settings
|
||||||
|
.cr/personal
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
||||||
|
# NVidia Nsight GPU debugger configuration file
|
||||||
|
*.nvuser
|
||||||
|
|
||||||
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
|
.mfractor/
|
||||||
|
|
||||||
|
# Local History for Visual Studio
|
||||||
|
.localhistory/
|
||||||
|
|
||||||
|
# BeatPulse healthcheck temp database
|
||||||
|
healthchecksdb
|
||||||
|
|
||||||
|
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||||
|
MigrationBackup/
|
||||||
|
|
||||||
|
# Ionide (cross platform F# VS Code tools) working folder
|
||||||
|
.ionide/
|
||||||
|
|
||||||
|
# Fody - auto-generated XML schema
|
||||||
|
FodyWeavers.xsd
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using YouTubeViewers.Domain.Models;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.Domain.Commands
|
||||||
|
{
|
||||||
|
public interface ICreateYouTubeViewerCommand
|
||||||
|
{
|
||||||
|
Task Execute(YouTubeViewer youTubeViewer);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.Domain.Commands
|
||||||
|
{
|
||||||
|
public interface IDeleteYouTubeViewerCommand
|
||||||
|
{
|
||||||
|
Task Execute(Guid id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using YouTubeViewers.Domain.Models;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.Domain.Commands
|
||||||
|
{
|
||||||
|
public interface IUpdateYouTubeViewerCommand
|
||||||
|
{
|
||||||
|
Task Execute(YouTubeViewer youTubeViewer);
|
||||||
|
}
|
||||||
|
}
|
||||||
24
YouTubeViewers.Domain/Models/YouTubeViewer.cs
Normal file
24
YouTubeViewers.Domain/Models/YouTubeViewer.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.Domain.Models
|
||||||
|
{
|
||||||
|
public class YouTubeViewer
|
||||||
|
{
|
||||||
|
public YouTubeViewer(Guid id, string username, bool isSubscribed, bool isMember)
|
||||||
|
{
|
||||||
|
Id = id;
|
||||||
|
Username = username;
|
||||||
|
IsSubscribed = isSubscribed;
|
||||||
|
IsMember = isMember;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Guid Id { get; }
|
||||||
|
public string Username { get; }
|
||||||
|
public bool IsSubscribed { get; }
|
||||||
|
public bool IsMember { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
14
YouTubeViewers.Domain/Queries/IGetAllYouTubeViewersQuery.cs
Normal file
14
YouTubeViewers.Domain/Queries/IGetAllYouTubeViewersQuery.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using YouTubeViewers.Domain.Models;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.Domain.Queries
|
||||||
|
{
|
||||||
|
public interface IGetAllYouTubeViewersQuery
|
||||||
|
{
|
||||||
|
Task<IEnumerable<YouTubeViewer>> Execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
9
YouTubeViewers.Domain/YouTubeViewers.Domain.csproj
Normal file
9
YouTubeViewers.Domain/YouTubeViewers.Domain.csproj
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using YouTubeViewers.Domain.Commands;
|
||||||
|
using YouTubeViewers.Domain.Models;
|
||||||
|
using YouTubeViewers.EntityFramework.DTOs;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.EntityFramework.Commands
|
||||||
|
{
|
||||||
|
public class CreateYouTubeViewerCommand :ICreateYouTubeViewerCommand
|
||||||
|
{
|
||||||
|
private readonly YouTubeViewersDbContextFactory _contextFactory;
|
||||||
|
|
||||||
|
public CreateYouTubeViewerCommand(YouTubeViewersDbContextFactory contextFactory)
|
||||||
|
{
|
||||||
|
_contextFactory = contextFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Execute(YouTubeViewer youTubeViewer)
|
||||||
|
{
|
||||||
|
using (YouTubeViewersDbContext context = _contextFactory.Create())
|
||||||
|
{
|
||||||
|
YouTubeViewerDto youTubeViewerDto = new YouTubeViewerDto()
|
||||||
|
{
|
||||||
|
Id = youTubeViewer.Id,
|
||||||
|
Username = youTubeViewer.Username,
|
||||||
|
IsSubscribed = youTubeViewer.IsSubscribed,
|
||||||
|
IsMember = youTubeViewer.IsMember,
|
||||||
|
};
|
||||||
|
|
||||||
|
context.YouTubeViewers.Add(youTubeViewerDto);
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using YouTubeViewers.Domain.Commands;
|
||||||
|
using YouTubeViewers.EntityFramework.DTOs;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.EntityFramework.Commands
|
||||||
|
{
|
||||||
|
public class DeleteYouTubeViewerCommand : IDeleteYouTubeViewerCommand
|
||||||
|
{
|
||||||
|
private readonly YouTubeViewersDbContextFactory _contextFactory;
|
||||||
|
|
||||||
|
public DeleteYouTubeViewerCommand(YouTubeViewersDbContextFactory contextFactory)
|
||||||
|
{
|
||||||
|
_contextFactory = contextFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Execute(Guid id)
|
||||||
|
{
|
||||||
|
using (YouTubeViewersDbContext context = _contextFactory.Create())
|
||||||
|
{
|
||||||
|
await Task.Delay(5000);
|
||||||
|
YouTubeViewerDto youTubeViewerDto = new YouTubeViewerDto()
|
||||||
|
{
|
||||||
|
Id = id,
|
||||||
|
};
|
||||||
|
|
||||||
|
context.YouTubeViewers.Remove(youTubeViewerDto);
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using YouTubeViewers.Domain.Commands;
|
||||||
|
using YouTubeViewers.Domain.Models;
|
||||||
|
using YouTubeViewers.EntityFramework.DTOs;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.EntityFramework.Commands
|
||||||
|
{
|
||||||
|
public class UpdateYouTubeViewerCommand : IUpdateYouTubeViewerCommand
|
||||||
|
{
|
||||||
|
private readonly YouTubeViewersDbContextFactory _contextFactory;
|
||||||
|
|
||||||
|
public UpdateYouTubeViewerCommand(YouTubeViewersDbContextFactory contextFactory)
|
||||||
|
{
|
||||||
|
_contextFactory = contextFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Execute(YouTubeViewer youTubeViewer)
|
||||||
|
{
|
||||||
|
using (YouTubeViewersDbContext context = _contextFactory.Create())
|
||||||
|
{
|
||||||
|
YouTubeViewerDto youTubeViewerDto = new YouTubeViewerDto()
|
||||||
|
{
|
||||||
|
Id = youTubeViewer.Id,
|
||||||
|
Username = youTubeViewer.Username,
|
||||||
|
IsSubscribed = youTubeViewer.IsSubscribed,
|
||||||
|
IsMember = youTubeViewer.IsMember,
|
||||||
|
};
|
||||||
|
|
||||||
|
context.YouTubeViewers.Update(youTubeViewerDto);
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
YouTubeViewers.EntityFramework/DTOs/YouTubeViewerDto.cs
Normal file
16
YouTubeViewers.EntityFramework/DTOs/YouTubeViewerDto.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.EntityFramework.DTOs
|
||||||
|
{
|
||||||
|
public class YouTubeViewerDto
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string Username { get; set; }
|
||||||
|
public bool IsSubscribed { get; set; }
|
||||||
|
public bool IsMember { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
45
YouTubeViewers.EntityFramework/Migrations/20220819131646_Initial.Designer.cs
generated
Normal file
45
YouTubeViewers.EntityFramework/Migrations/20220819131646_Initial.Designer.cs
generated
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using YouTubeViewers.EntityFramework;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace YouTubeViewers.EntityFramework.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(YouTubeViewersDbContext))]
|
||||||
|
[Migration("20220819131646_Initial")]
|
||||||
|
partial class Initial
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder.HasAnnotation("ProductVersion", "6.0.8");
|
||||||
|
|
||||||
|
modelBuilder.Entity("YouTubeViewers.EntityFramework.DTOs.YouTubeViewerDto", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<bool>("IsMember")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSubscribed")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("YouTubeViewers");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace YouTubeViewers.EntityFramework.Migrations
|
||||||
|
{
|
||||||
|
public partial class Initial : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "YouTubeViewers",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||||
|
Username = table.Column<string>(type: "TEXT", nullable: false),
|
||||||
|
IsSubscribed = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||||
|
IsMember = table.Column<bool>(type: "INTEGER", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_YouTubeViewers", x => x.Id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "YouTubeViewers");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using YouTubeViewers.EntityFramework;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace YouTubeViewers.EntityFramework.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(YouTubeViewersDbContext))]
|
||||||
|
partial class YouTubeViewersDbContextModelSnapshot : ModelSnapshot
|
||||||
|
{
|
||||||
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder.HasAnnotation("ProductVersion", "6.0.8");
|
||||||
|
|
||||||
|
modelBuilder.Entity("YouTubeViewers.EntityFramework.DTOs.YouTubeViewerDto", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<bool>("IsMember")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSubscribed")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("YouTubeViewers");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using YouTubeViewers.Domain.Models;
|
||||||
|
using YouTubeViewers.Domain.Queries;
|
||||||
|
using YouTubeViewers.EntityFramework.DTOs;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.EntityFramework.Queries
|
||||||
|
{
|
||||||
|
public class GetAllYouTubeViewersQuery : IGetAllYouTubeViewersQuery
|
||||||
|
{
|
||||||
|
private readonly YouTubeViewersDbContextFactory _contextFactory;
|
||||||
|
|
||||||
|
public GetAllYouTubeViewersQuery(YouTubeViewersDbContextFactory contextFactory)
|
||||||
|
{
|
||||||
|
_contextFactory = contextFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<YouTubeViewer>> Execute()
|
||||||
|
{
|
||||||
|
using (YouTubeViewersDbContext context = _contextFactory.Create())
|
||||||
|
{
|
||||||
|
//await Task.Delay(5000);
|
||||||
|
|
||||||
|
IEnumerable<YouTubeViewerDto> youTubeViewerDtos = await context.YouTubeViewers.ToListAsync();
|
||||||
|
|
||||||
|
return youTubeViewerDtos.Select(y => new YouTubeViewer(y.Id, y.Username, y.IsSubscribed, y.IsMember));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.8" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.8">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.8" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\YouTubeViewers.Domain\YouTubeViewers.Domain.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
24
YouTubeViewers.EntityFramework/YouTubeViewersDbContext.cs
Normal file
24
YouTubeViewers.EntityFramework/YouTubeViewersDbContext.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using YouTubeViewers.EntityFramework.DTOs;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.EntityFramework
|
||||||
|
{
|
||||||
|
public class YouTubeViewersDbContext : DbContext
|
||||||
|
{
|
||||||
|
public YouTubeViewersDbContext(DbContextOptions options) : base(options) { }
|
||||||
|
|
||||||
|
public DbSet<YouTubeViewerDto> YouTubeViewers { get; set; }
|
||||||
|
|
||||||
|
//DbContextOptions options = new DbContextOptionsBuilder()
|
||||||
|
// .UseSqlite(_connectionString)
|
||||||
|
// .Options;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.EntityFramework
|
||||||
|
{
|
||||||
|
public class YouTubeViewersDbContextFactory
|
||||||
|
{
|
||||||
|
private readonly DbContextOptions _options;
|
||||||
|
|
||||||
|
public YouTubeViewersDbContextFactory(DbContextOptions options)
|
||||||
|
{
|
||||||
|
_options = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
public YouTubeViewersDbContext Create()
|
||||||
|
{
|
||||||
|
|
||||||
|
return new YouTubeViewersDbContext(_options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Design;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.EntityFramework
|
||||||
|
{
|
||||||
|
public class YouTubeViewersDesignTimeDbContextFactory : IDesignTimeDbContextFactory<YouTubeViewersDbContext>
|
||||||
|
{
|
||||||
|
public YouTubeViewersDbContext CreateDbContext(string[] args = null)
|
||||||
|
{
|
||||||
|
return new YouTubeViewersDbContext(new DbContextOptionsBuilder().UseSqlite("Data Source=YouTubeViewers.db").Options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
94
YouTubeViewers.WPF/App.xaml
Normal file
94
YouTubeViewers.WPF/App.xaml
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<Application x:Class="YouTubeViewers.WPF.App"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="clr-namespace:YouTubeViewers.WPF">
|
||||||
|
<Application.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<SolidColorBrush x:Key="BorderPrimary" Color="#1c1c1c" />
|
||||||
|
|
||||||
|
<Style x:Key="PageHeader" TargetType="TextBlock" >
|
||||||
|
<Setter Property="FontSize" Value="32" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Button">
|
||||||
|
<Setter Property="Foreground" Value="White" />
|
||||||
|
<Setter Property="Background" Value="#547AFF" />
|
||||||
|
<Setter Property="Padding" Value="20 8" />
|
||||||
|
<Setter Property="Cursor" Value="Hand" />
|
||||||
|
<Setter Property="VerticalAlignment" Value="Center" />
|
||||||
|
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||||
|
<Setter Property="TextBlock.TextAlignment" Value="Center" />
|
||||||
|
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Border Margin="{TemplateBinding Margin}"
|
||||||
|
Padding="{TemplateBinding Padding}"
|
||||||
|
Background="{TemplateBinding Background}"
|
||||||
|
CornerRadius="3" >
|
||||||
|
<ContentPresenter />
|
||||||
|
</Border>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
|
||||||
|
<Style.Triggers>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Trigger.EnterActions>
|
||||||
|
<BeginStoryboard>
|
||||||
|
<Storyboard>
|
||||||
|
<ColorAnimation
|
||||||
|
Storyboard.TargetProperty="Background.(SolidColorBrush.Color)"
|
||||||
|
To="#2a3d82" Duration="0:0:0.1" />
|
||||||
|
</Storyboard>
|
||||||
|
</BeginStoryboard>
|
||||||
|
</Trigger.EnterActions>
|
||||||
|
<Trigger.ExitActions>
|
||||||
|
<BeginStoryboard>
|
||||||
|
<Storyboard>
|
||||||
|
<ColorAnimation
|
||||||
|
Storyboard.TargetProperty="Background.(SolidColorBrush.Color)"
|
||||||
|
To="#547AFF" Duration="0:0:0.1" />
|
||||||
|
</Storyboard>
|
||||||
|
</BeginStoryboard>
|
||||||
|
</Trigger.ExitActions>
|
||||||
|
</Trigger>
|
||||||
|
<Trigger Property="IsEnabled" Value="False">
|
||||||
|
<Setter Property="Opacity" Value="0.7" />
|
||||||
|
</Trigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
<Style
|
||||||
|
x:Key="ButtonSecondary"
|
||||||
|
BasedOn="{StaticResource {x:Type Button}}"
|
||||||
|
TargetType="Button">
|
||||||
|
<Setter Property="Foreground" Value="Black" />
|
||||||
|
<Setter Property="Background" Value="#E1E1E1" />
|
||||||
|
|
||||||
|
<Style.Triggers>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Trigger.EnterActions>
|
||||||
|
<BeginStoryboard>
|
||||||
|
<Storyboard>
|
||||||
|
<ColorAnimation
|
||||||
|
Storyboard.TargetProperty="Background.(SolidColorBrush.Color)"
|
||||||
|
To="#c2c2c2" Duration="0:0:0.1" />
|
||||||
|
</Storyboard>
|
||||||
|
</BeginStoryboard>
|
||||||
|
</Trigger.EnterActions>
|
||||||
|
<Trigger.ExitActions>
|
||||||
|
<BeginStoryboard>
|
||||||
|
<Storyboard>
|
||||||
|
<ColorAnimation
|
||||||
|
Storyboard.TargetProperty="Background.(SolidColorBrush.Color)"
|
||||||
|
To="#E1E1E1" Duration="0:0:0.1" />
|
||||||
|
</Storyboard>
|
||||||
|
</BeginStoryboard>
|
||||||
|
</Trigger.ExitActions>
|
||||||
|
</Trigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
</ResourceDictionary>
|
||||||
|
</Application.Resources>
|
||||||
|
</Application>
|
||||||
78
YouTubeViewers.WPF/App.xaml.cs
Normal file
78
YouTubeViewers.WPF/App.xaml.cs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Configuration;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using YouTubeViewers.Domain.Commands;
|
||||||
|
using YouTubeViewers.Domain.Queries;
|
||||||
|
using YouTubeViewers.EntityFramework;
|
||||||
|
using YouTubeViewers.EntityFramework.Commands;
|
||||||
|
using YouTubeViewers.EntityFramework.Queries;
|
||||||
|
using YouTubeViewers.WPF.Stores;
|
||||||
|
using YouTubeViewers.WPF.ViewModels;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF;
|
||||||
|
|
||||||
|
public partial class App : Application
|
||||||
|
{
|
||||||
|
private readonly ModalNavigationStore _modalNavigationStore;
|
||||||
|
private readonly YouTubeViewersDbContextFactory _youTubeViewersDbContextFactory;
|
||||||
|
private readonly IGetAllYouTubeViewersQuery _getAllYouTubeViewersQuery;
|
||||||
|
private readonly ICreateYouTubeViewerCommand _createYouTubeViewerCommand;
|
||||||
|
private readonly IUpdateYouTubeViewerCommand _updateYouTubeViewerCommand;
|
||||||
|
private readonly IDeleteYouTubeViewerCommand _deleteYouTubeViewerCommand;
|
||||||
|
private readonly YouTubeViewersStore _youTubeViewersStore;
|
||||||
|
private readonly SelectedYouTubeViewerStore _selectedYouTubeViewerStore;
|
||||||
|
|
||||||
|
public App()
|
||||||
|
{
|
||||||
|
string connectionString = "Data Source=YouTubeViewers.db";
|
||||||
|
_modalNavigationStore = new ModalNavigationStore();
|
||||||
|
_youTubeViewersDbContextFactory = new YouTubeViewersDbContextFactory(
|
||||||
|
new DbContextOptionsBuilder()
|
||||||
|
.UseSqlite(connectionString)
|
||||||
|
.Options
|
||||||
|
);
|
||||||
|
_getAllYouTubeViewersQuery = new GetAllYouTubeViewersQuery(_youTubeViewersDbContextFactory);
|
||||||
|
_createYouTubeViewerCommand = new CreateYouTubeViewerCommand(_youTubeViewersDbContextFactory);
|
||||||
|
_updateYouTubeViewerCommand = new UpdateYouTubeViewerCommand(_youTubeViewersDbContextFactory);
|
||||||
|
_deleteYouTubeViewerCommand = new DeleteYouTubeViewerCommand(_youTubeViewersDbContextFactory);
|
||||||
|
_youTubeViewersStore = new YouTubeViewersStore(
|
||||||
|
_getAllYouTubeViewersQuery,
|
||||||
|
_createYouTubeViewerCommand,
|
||||||
|
_updateYouTubeViewerCommand,
|
||||||
|
_deleteYouTubeViewerCommand
|
||||||
|
);
|
||||||
|
_selectedYouTubeViewerStore = new SelectedYouTubeViewerStore(_youTubeViewersStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnStartup(StartupEventArgs e)
|
||||||
|
{
|
||||||
|
using(YouTubeViewersDbContext context = _youTubeViewersDbContextFactory.Create())
|
||||||
|
{
|
||||||
|
//context.Database.EnsureCreated();
|
||||||
|
context.Database.Migrate();
|
||||||
|
}
|
||||||
|
|
||||||
|
YouTubeViewersViewModel youTubeViewersViewModel = YouTubeViewersViewModel.LoadViewModel(
|
||||||
|
_youTubeViewersStore,
|
||||||
|
_selectedYouTubeViewerStore,
|
||||||
|
_modalNavigationStore);
|
||||||
|
|
||||||
|
MainWindow = new MainWindow()
|
||||||
|
{
|
||||||
|
DataContext = new MainViewModel(_modalNavigationStore, youTubeViewersViewModel)
|
||||||
|
};
|
||||||
|
|
||||||
|
MainWindow.Show();
|
||||||
|
|
||||||
|
base.OnStartup(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
10
YouTubeViewers.WPF/AssemblyInfo.cs
Normal file
10
YouTubeViewers.WPF/AssemblyInfo.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
[assembly: ThemeInfo(
|
||||||
|
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||||
|
//(used if a resource is not found in the page,
|
||||||
|
// or application resource dictionaries)
|
||||||
|
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||||
|
//(used if a resource is not found in the page,
|
||||||
|
// app, or any theme specific resource dictionaries)
|
||||||
|
)]
|
||||||
50
YouTubeViewers.WPF/Commands/AddYouTubeViewerCommand.cs
Normal file
50
YouTubeViewers.WPF/Commands/AddYouTubeViewerCommand.cs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using YouTubeViewers.Domain.Models;
|
||||||
|
using YouTubeViewers.WPF.Stores;
|
||||||
|
using YouTubeViewers.WPF.ViewModels;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.Commands
|
||||||
|
{
|
||||||
|
public class AddYouTubeViewerCommand : AsyncCommandBase
|
||||||
|
{
|
||||||
|
private readonly AddYouTubeViewerViewModel _addYouTubeViewerViewModel;
|
||||||
|
private readonly YouTubeViewersStore _youTubeViewersStore;
|
||||||
|
private readonly ModalNavigationStore _modalNavigationStore;
|
||||||
|
|
||||||
|
public AddYouTubeViewerCommand(AddYouTubeViewerViewModel addYouTubeViewerViewModel, YouTubeViewersStore youTubeViewersStore, ModalNavigationStore modalNavigationStore)
|
||||||
|
{
|
||||||
|
_addYouTubeViewerViewModel = addYouTubeViewerViewModel;
|
||||||
|
_youTubeViewersStore = youTubeViewersStore;
|
||||||
|
_modalNavigationStore = modalNavigationStore;
|
||||||
|
}
|
||||||
|
public override async Task ExecuteAsync(object? parameter)
|
||||||
|
{
|
||||||
|
YouTubeViewerDetailsFormViewModel formViewModel = _addYouTubeViewerViewModel.YouTubeViewerDetailsFormViewModel;
|
||||||
|
formViewModel.IsSubmitting = true;
|
||||||
|
YouTubeViewer youTubeViewer = new YouTubeViewer(
|
||||||
|
Guid.NewGuid(),
|
||||||
|
formViewModel.UserName,
|
||||||
|
formViewModel.IsSubScribed,
|
||||||
|
formViewModel.IsMember);
|
||||||
|
|
||||||
|
// Add YouTubeViewer to database
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _youTubeViewersStore.Add(youTubeViewer);
|
||||||
|
_modalNavigationStore.Close();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
formViewModel.IsSubmitting = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
44
YouTubeViewers.WPF/Commands/AsyncCommandBase.cs
Normal file
44
YouTubeViewers.WPF/Commands/AsyncCommandBase.cs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.Commands
|
||||||
|
{
|
||||||
|
public abstract class AsyncCommandBase : CommandBase
|
||||||
|
{
|
||||||
|
private bool _isExecuting;
|
||||||
|
|
||||||
|
public bool IsExecuting
|
||||||
|
{
|
||||||
|
get { return _isExecuting; }
|
||||||
|
set { _isExecuting = value;
|
||||||
|
OnCanExecuteChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanExecute(object? parameter)
|
||||||
|
{
|
||||||
|
return !_isExecuting && base.CanExecute(parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override async void Execute(object? parameter)
|
||||||
|
{
|
||||||
|
IsExecuting = true;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await ExecuteAsync(parameter);
|
||||||
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IsExecuting = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Task ExecuteAsync(object? parameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
24
YouTubeViewers.WPF/Commands/CloseModalCommand.cs
Normal file
24
YouTubeViewers.WPF/Commands/CloseModalCommand.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using YouTubeViewers.WPF.Stores;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.Commands
|
||||||
|
{
|
||||||
|
public class CloseModalCommand : CommandBase
|
||||||
|
{
|
||||||
|
private readonly ModalNavigationStore _modalNavigationStore;
|
||||||
|
|
||||||
|
public CloseModalCommand(ModalNavigationStore modalNavigationStore)
|
||||||
|
{
|
||||||
|
_modalNavigationStore = modalNavigationStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Execute(object? parameter)
|
||||||
|
{
|
||||||
|
_modalNavigationStore.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
YouTubeViewers.WPF/Commands/CommandBase.cs
Normal file
26
YouTubeViewers.WPF/Commands/CommandBase.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Input;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.Commands
|
||||||
|
{
|
||||||
|
public abstract class CommandBase : ICommand
|
||||||
|
{
|
||||||
|
public event EventHandler? CanExecuteChanged;
|
||||||
|
|
||||||
|
public virtual bool CanExecute(object? parameter)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void Execute(object? parameter);
|
||||||
|
|
||||||
|
protected virtual void OnCanExecuteChanged()
|
||||||
|
{
|
||||||
|
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
YouTubeViewers.WPF/Commands/DeleteYouTubeViewerCommand.cs
Normal file
39
YouTubeViewers.WPF/Commands/DeleteYouTubeViewerCommand.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using YouTubeViewers.Domain.Models;
|
||||||
|
using YouTubeViewers.WPF.Stores;
|
||||||
|
using YouTubeViewers.WPF.ViewModels;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.Commands
|
||||||
|
{
|
||||||
|
public class DeleteYouTubeViewerCommand : AsyncCommandBase
|
||||||
|
{
|
||||||
|
private readonly YouTubeViewersListingItemViewModel _youTubeViewersListingItemViewModel;
|
||||||
|
private readonly YouTubeViewersStore _youTubeViewersStore;
|
||||||
|
|
||||||
|
public DeleteYouTubeViewerCommand(
|
||||||
|
YouTubeViewersListingItemViewModel youTubeViewersListingItemViewModel,
|
||||||
|
YouTubeViewersStore youTubeViewersStore)
|
||||||
|
{
|
||||||
|
_youTubeViewersListingItemViewModel = youTubeViewersListingItemViewModel;
|
||||||
|
_youTubeViewersStore = youTubeViewersStore;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task ExecuteAsync(object? parameter)
|
||||||
|
{
|
||||||
|
YouTubeViewer youTubeViewer = _youTubeViewersListingItemViewModel.YouTubeViewer;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _youTubeViewersStore.Delete(youTubeViewer.Id);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
50
YouTubeViewers.WPF/Commands/EditYouTubeViewerCommand.cs
Normal file
50
YouTubeViewers.WPF/Commands/EditYouTubeViewerCommand.cs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using YouTubeViewers.Domain.Models;
|
||||||
|
using YouTubeViewers.WPF.Stores;
|
||||||
|
using YouTubeViewers.WPF.ViewModels;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.Commands
|
||||||
|
{
|
||||||
|
public class EditYouTubeViewerCommand : AsyncCommandBase
|
||||||
|
{
|
||||||
|
private readonly EditYouTubeViewerViewModel _editYouTubeViewerViewModel;
|
||||||
|
private readonly YouTubeViewersStore _youTubeViewersStore;
|
||||||
|
private readonly ModalNavigationStore _modalNavigationStore;
|
||||||
|
|
||||||
|
public EditYouTubeViewerCommand(EditYouTubeViewerViewModel editYouTubeViewerViewModel, YouTubeViewersStore youTubeViewersStore, ModalNavigationStore modalNavigationStore)
|
||||||
|
{
|
||||||
|
_editYouTubeViewerViewModel = editYouTubeViewerViewModel;
|
||||||
|
_youTubeViewersStore = youTubeViewersStore;
|
||||||
|
_modalNavigationStore = modalNavigationStore;
|
||||||
|
}
|
||||||
|
public override async Task ExecuteAsync(object? parameter)
|
||||||
|
{
|
||||||
|
YouTubeViewerDetailsFormViewModel formViewModel = _editYouTubeViewerViewModel.YouTubeViewerDetailsFormViewModel;
|
||||||
|
formViewModel.IsSubmitting = true;
|
||||||
|
YouTubeViewer youTubeViewer = new YouTubeViewer(
|
||||||
|
_editYouTubeViewerViewModel.YouTubeViewerId,
|
||||||
|
formViewModel.UserName,
|
||||||
|
formViewModel.IsSubScribed,
|
||||||
|
formViewModel.IsMember);
|
||||||
|
|
||||||
|
// Add YouTubeViewer to database
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _youTubeViewersStore.Update(youTubeViewer);
|
||||||
|
_modalNavigationStore.Close();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
formViewModel.IsSubmitting = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
40
YouTubeViewers.WPF/Commands/LoadYouTubeViewersCommand.cs
Normal file
40
YouTubeViewers.WPF/Commands/LoadYouTubeViewersCommand.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using YouTubeViewers.WPF.Stores;
|
||||||
|
using YouTubeViewers.WPF.ViewModels;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.Commands
|
||||||
|
{
|
||||||
|
public class LoadYouTubeViewersCommand : AsyncCommandBase
|
||||||
|
{
|
||||||
|
private readonly YouTubeViewersViewModel _youTubeViewersViewModel;
|
||||||
|
private readonly YouTubeViewersStore _youTubeViewersStore;
|
||||||
|
|
||||||
|
public LoadYouTubeViewersCommand(YouTubeViewersViewModel youTubeViewersViewModel, YouTubeViewersStore youTubeViewersStore)
|
||||||
|
{
|
||||||
|
_youTubeViewersViewModel = youTubeViewersViewModel;
|
||||||
|
_youTubeViewersStore = youTubeViewersStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task ExecuteAsync(object? parameter)
|
||||||
|
{
|
||||||
|
_youTubeViewersViewModel.IsLoading = true;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _youTubeViewersStore.Load();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_youTubeViewersViewModel.IsLoading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
YouTubeViewers.WPF/Commands/OpenAddYouTubeViewerCommand.cs
Normal file
29
YouTubeViewers.WPF/Commands/OpenAddYouTubeViewerCommand.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using YouTubeViewers.WPF.Stores;
|
||||||
|
using YouTubeViewers.WPF.ViewModels;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.Commands
|
||||||
|
{
|
||||||
|
public class OpenAddYouTubeViewerCommand : CommandBase
|
||||||
|
{
|
||||||
|
private readonly YouTubeViewersStore _youTubeViewersStore;
|
||||||
|
private readonly ModalNavigationStore _modalNavigationStore;
|
||||||
|
|
||||||
|
public OpenAddYouTubeViewerCommand(YouTubeViewersStore youTubeViewersStore, ModalNavigationStore modalNavigationStore)
|
||||||
|
{
|
||||||
|
_youTubeViewersStore = youTubeViewersStore;
|
||||||
|
_modalNavigationStore = modalNavigationStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Execute(object? parameter)
|
||||||
|
{
|
||||||
|
AddYouTubeViewerViewModel addYouTubeViewerViewModel = new AddYouTubeViewerViewModel(_youTubeViewersStore, _modalNavigationStore);
|
||||||
|
_modalNavigationStore.CurrentViewModel = addYouTubeViewerViewModel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
YouTubeViewers.WPF/Commands/OpenEditYouTubeViewerCommand.cs
Normal file
38
YouTubeViewers.WPF/Commands/OpenEditYouTubeViewerCommand.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using YouTubeViewers.Domain.Models;
|
||||||
|
using YouTubeViewers.WPF.Stores;
|
||||||
|
using YouTubeViewers.WPF.ViewModels;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.Commands
|
||||||
|
{
|
||||||
|
public class OpenEditYouTubeViewerCommand: CommandBase
|
||||||
|
{
|
||||||
|
private readonly YouTubeViewersListingItemViewModel _youTubeViewersListingItemViewModel;
|
||||||
|
private readonly YouTubeViewersStore _youTubeViewersStore;
|
||||||
|
private readonly ModalNavigationStore _modalNavigationStore;
|
||||||
|
|
||||||
|
public OpenEditYouTubeViewerCommand(
|
||||||
|
YouTubeViewersListingItemViewModel youTubeViewersListingItemViewModel,
|
||||||
|
YouTubeViewersStore youTubeViewersStore,
|
||||||
|
ModalNavigationStore modalNavigationStore)
|
||||||
|
{
|
||||||
|
_youTubeViewersListingItemViewModel = youTubeViewersListingItemViewModel;
|
||||||
|
_youTubeViewersStore = youTubeViewersStore;
|
||||||
|
_modalNavigationStore = modalNavigationStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Execute(object? parameter)
|
||||||
|
{
|
||||||
|
YouTubeViewer youTubeViewer = _youTubeViewersListingItemViewModel.YouTubeViewer;
|
||||||
|
|
||||||
|
EditYouTubeViewerViewModel editYouTubeViewerViewModel = new EditYouTubeViewerViewModel(youTubeViewer,_youTubeViewersStore, _modalNavigationStore);
|
||||||
|
_modalNavigationStore.CurrentViewModel = editYouTubeViewerViewModel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
70
YouTubeViewers.WPF/Components/YouTubeViewerDetailsForm.xaml
Normal file
70
YouTubeViewers.WPF/Components/YouTubeViewerDetailsForm.xaml
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<UserControl x:Class="YouTubeViewers.WPF.Components.YouTubeViewerDetailsForm"
|
||||||
|
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:YouTubeViewers.WPF.Components"
|
||||||
|
xmlns:custom="clr-namespace:LoadingSpinnerControl;assembly=LoadingSpinnerControl"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="auto"/>
|
||||||
|
<RowDefinition Height="auto"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid Grid.IsSharedSizeScope="True">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="auto"/>
|
||||||
|
<RowDefinition Height="auto"/>
|
||||||
|
<RowDefinition Height="auto"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
|
||||||
|
<Grid Grid.Row="0" >
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="auto" SharedSizeGroup="Label"/>
|
||||||
|
<ColumnDefinition Width="*" MaxWidth="250"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Grid.Column="0" Text="Username" FontWeight="Bold" />
|
||||||
|
<TextBox Margin="20 0 0 0"
|
||||||
|
Grid.Column="1"
|
||||||
|
Text="{Binding UserName, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid Grid.Row="1" Margin="0 20 0 0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="auto" SharedSizeGroup="Label"/>
|
||||||
|
<ColumnDefinition Width="auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Grid.Column="0" Text="Is Subscribed?" FontWeight="Bold" />
|
||||||
|
<CheckBox Margin="20 0 0 0"
|
||||||
|
Grid.Column="1"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
IsChecked="{Binding IsSubScribed}" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid Grid.Row="2" Margin="0 20 0 0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="auto" SharedSizeGroup="Label"/>
|
||||||
|
<ColumnDefinition Width="auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Grid.Column="0" Text="Is Member?" FontWeight="Bold" />
|
||||||
|
<CheckBox Margin="20 0 0 0"
|
||||||
|
Grid.Column="1"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
IsChecked="{Binding IsMember}" />
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
<WrapPanel Grid.Row="1" Margin="0 30 0 0">
|
||||||
|
<Button Margin="0 0 5 0"
|
||||||
|
Command="{Binding SubmitCommand}"
|
||||||
|
Content="Submit"
|
||||||
|
IsEnabled="{Binding CanSubmit}"/>
|
||||||
|
|
||||||
|
<Button Margin="0 0 5 0" Command="{Binding CancelCommand}"
|
||||||
|
Content="Cancel"
|
||||||
|
Style="{StaticResource ButtonSecondary}"/>
|
||||||
|
<custom:LoadingSpinner IsLoading="{Binding IsSubmitting}" Diameter="25" Thickness="2"/>
|
||||||
|
</WrapPanel>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Windows.Navigation;
|
||||||
|
using System.Windows.Shapes;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.Components
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for YouTubeViewerDetailsForm.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class YouTubeViewerDetailsForm : UserControl
|
||||||
|
{
|
||||||
|
public YouTubeViewerDetailsForm()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
73
YouTubeViewers.WPF/Components/YouTubeViewersDetails.xaml
Normal file
73
YouTubeViewers.WPF/Components/YouTubeViewersDetails.xaml
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<UserControl x:Class="YouTubeViewers.WPF.Components.YouTubeViewersDetails"
|
||||||
|
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:YouTubeViewers.WPF.Components"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
|
<Grid>
|
||||||
|
<Border Padding="20" BorderBrush="{StaticResource BorderPrimary}"
|
||||||
|
BorderThickness="1" CornerRadius="5"
|
||||||
|
SnapsToDevicePixels="True">
|
||||||
|
<Grid>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Style>
|
||||||
|
<Style TargetType="Grid">
|
||||||
|
<Setter Property="Visibility" Value="Collapsed"/>
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding HasSelectedYouTubeViewer}" Value="false">
|
||||||
|
<Setter Property="Visibility" Value="Visible"/>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</Grid.Style>
|
||||||
|
<TextBlock Grid.Row="0"
|
||||||
|
Text="Please select a YouTube Viewer to see their details." />
|
||||||
|
</Grid>
|
||||||
|
<Grid Grid.IsSharedSizeScope="True">
|
||||||
|
<Grid.Style>
|
||||||
|
<Style TargetType="Grid">
|
||||||
|
<Setter Property="Visibility" Value="Collapsed"/>
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding HasSelectedYouTubeViewer}" Value="True">
|
||||||
|
<Setter Property="Visibility" Value="Visible"/>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</Grid.Style>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="auto"/>
|
||||||
|
<RowDefinition Height="auto"/>
|
||||||
|
<RowDefinition Height="auto"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<TextBlock Grid.Row="0"
|
||||||
|
FontSize="24"
|
||||||
|
Text="{Binding UserName}" />
|
||||||
|
|
||||||
|
<Grid Grid.Row="1" Margin="0 20 0 0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="auto" SharedSizeGroup="Label"/>
|
||||||
|
<ColumnDefinition Width="auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Grid.Column="0" Text="Is Subscribed?" FontWeight="Bold" />
|
||||||
|
<TextBlock Margin="20 0 0 0"
|
||||||
|
Grid.Column="1"
|
||||||
|
Text="{Binding IsSubScribedDisplay}" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid Grid.Row="2" Margin="0 20 0 0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="auto" SharedSizeGroup="Label"/>
|
||||||
|
<ColumnDefinition Width="auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Grid.Column="0" Text="Is Member?" FontWeight="Bold" />
|
||||||
|
<TextBlock Margin="20 0 0 0"
|
||||||
|
Grid.Column="1"
|
||||||
|
Text="{Binding IsMemberDisplay}" />
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
28
YouTubeViewers.WPF/Components/YouTubeViewersDetails.xaml.cs
Normal file
28
YouTubeViewers.WPF/Components/YouTubeViewersDetails.xaml.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Windows.Navigation;
|
||||||
|
using System.Windows.Shapes;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.Components
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for YouTubeViewersDetails.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class YouTubeViewersDetails : UserControl
|
||||||
|
{
|
||||||
|
public YouTubeViewersDetails()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
41
YouTubeViewers.WPF/Components/YouTubeViewersListing.xaml
Normal file
41
YouTubeViewers.WPF/Components/YouTubeViewersListing.xaml
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<UserControl x:Class="YouTubeViewers.WPF.Components.YouTubeViewersListing"
|
||||||
|
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:YouTubeViewers.WPF.Components"
|
||||||
|
xmlns:custom="clr-namespace:DropdownMenuControl;assembly=DropdownMenuControl"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
|
<Grid>
|
||||||
|
<Border
|
||||||
|
BorderBrush="{StaticResource BorderPrimary}"
|
||||||
|
BorderThickness="1"
|
||||||
|
CornerRadius="5"
|
||||||
|
SnapsToDevicePixels="True">
|
||||||
|
<Grid>
|
||||||
|
<Grid.OpacityMask>
|
||||||
|
<VisualBrush Visual="{Binding ElementName=border}"/>
|
||||||
|
</Grid.OpacityMask>
|
||||||
|
<Border
|
||||||
|
x:Name="border"
|
||||||
|
Background="White"
|
||||||
|
CornerRadius="5"/>
|
||||||
|
<ListView BorderThickness="0"
|
||||||
|
ItemsSource="{Binding YouTubeViewersListingItemViewModels}"
|
||||||
|
SelectedItem="{Binding SelectedYouTubeViewerListingItemViewModel}">
|
||||||
|
<ListView.ItemContainerStyle>
|
||||||
|
<Style TargetType="ListViewItem">
|
||||||
|
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
||||||
|
</Style>
|
||||||
|
</ListView.ItemContainerStyle>
|
||||||
|
<ListView.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<local:YouTubeViewersListingItem/>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListView.ItemTemplate>
|
||||||
|
</ListView>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
28
YouTubeViewers.WPF/Components/YouTubeViewersListing.xaml.cs
Normal file
28
YouTubeViewers.WPF/Components/YouTubeViewersListing.xaml.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Windows.Navigation;
|
||||||
|
using System.Windows.Shapes;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.Components
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for YouTubeViewersListing.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class YouTubeViewersListing : UserControl
|
||||||
|
{
|
||||||
|
public YouTubeViewersListing()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
80
YouTubeViewers.WPF/Components/YouTubeViewersListingItem.xaml
Normal file
80
YouTubeViewers.WPF/Components/YouTubeViewersListingItem.xaml
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
<UserControl x:Class="YouTubeViewers.WPF.Components.YouTubeViewersListingItem"
|
||||||
|
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:YouTubeViewers.WPF.Components"
|
||||||
|
xmlns:custom="clr-namespace:DropdownMenuControl;assembly=DropdownMenuControl"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
|
<Border Padding="10" TextBlock.FontSize="16">
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<TextBlock Grid.Column="0" Text="{Binding UserName}"/>
|
||||||
|
|
||||||
|
<custom:DropdownMenu x:Name="dropdown" Grid.Column="1" Margin="10 0 0 0">
|
||||||
|
<Border
|
||||||
|
Background="White"
|
||||||
|
BorderThickness="1"
|
||||||
|
BorderBrush="Gray">
|
||||||
|
<StackPanel MinWidth="125">
|
||||||
|
<StackPanel.Resources>
|
||||||
|
<Style TargetType="Button">
|
||||||
|
<Setter Property="Background" Value="#f0f0f0"/>
|
||||||
|
<Setter Property="Foreground" Value="Black"/>
|
||||||
|
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||||
|
<Setter Property="Padding" Value="20 10"/>
|
||||||
|
<Setter Property="Cursor" Value="Hand"/>
|
||||||
|
<EventSetter Event="Click" Handler="Button_Click"/>
|
||||||
|
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Border
|
||||||
|
Margin="{TemplateBinding Margin}"
|
||||||
|
Padding="{TemplateBinding Padding}"
|
||||||
|
Background="{TemplateBinding Background}">
|
||||||
|
<ContentPresenter />
|
||||||
|
</Border>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
|
||||||
|
<Style.Triggers>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Trigger.EnterActions>
|
||||||
|
<BeginStoryboard>
|
||||||
|
<Storyboard>
|
||||||
|
<ColorAnimation
|
||||||
|
Storyboard.TargetProperty="Background.(SolidColorBrush.Color)"
|
||||||
|
To="#c7c7c7"
|
||||||
|
Duration="0:0:0.1" />
|
||||||
|
</Storyboard>
|
||||||
|
</BeginStoryboard>
|
||||||
|
</Trigger.EnterActions>
|
||||||
|
<Trigger.ExitActions>
|
||||||
|
<BeginStoryboard>
|
||||||
|
<Storyboard>
|
||||||
|
<ColorAnimation
|
||||||
|
Storyboard.TargetProperty="Background.(SolidColorBrush.Color)"
|
||||||
|
To="#f0f0f0"
|
||||||
|
Duration="0:0:0.1" />
|
||||||
|
</Storyboard>
|
||||||
|
</BeginStoryboard>
|
||||||
|
</Trigger.ExitActions>
|
||||||
|
</Trigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</StackPanel.Resources>
|
||||||
|
<Button Content="Edit" Command="{Binding EditCommand}"/>
|
||||||
|
<Button Content="Delete" Command="{Binding DeleteCommand}"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</custom:DropdownMenu>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</UserControl>
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Windows.Navigation;
|
||||||
|
using System.Windows.Shapes;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.Components
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for YouTubeViewersListingItem.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class YouTubeViewersListingItem : UserControl
|
||||||
|
{
|
||||||
|
public YouTubeViewersListingItem()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Button_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
dropdown.IsOpen = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
YouTubeViewers.WPF/MainWindow.xaml
Normal file
34
YouTubeViewers.WPF/MainWindow.xaml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<Window x:Class="YouTubeViewers.WPF.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:YouTubeViewers.WPF"
|
||||||
|
xmlns:vms ="clr-namespace:YouTubeViewers.WPF.ViewModels"
|
||||||
|
xmlns:views="clr-namespace:YouTubeViewers.WPF.Views"
|
||||||
|
xmlns:viewmodels="clr-namespace:YouTubeViewers.WPF.ViewModels"
|
||||||
|
xmlns:custom="clr-namespace:ModalControl;assembly=ModalControl"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
Title="YouTube Viewers"
|
||||||
|
Height="450"
|
||||||
|
Width="800"
|
||||||
|
FontSize="14"
|
||||||
|
WindowStartupLocation="CenterScreen">
|
||||||
|
<Window.Resources>
|
||||||
|
<DataTemplate DataType="{x:Type vms:AddYouTubeViewerViewModel}">
|
||||||
|
<views:AddYouTubeViewerView/>
|
||||||
|
</DataTemplate>
|
||||||
|
<DataTemplate DataType="{x:Type vms:EditYouTubeViewerViewModel}">
|
||||||
|
<views:EditYouTubeViewerView/>
|
||||||
|
</DataTemplate>
|
||||||
|
</Window.Resources>
|
||||||
|
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
|
||||||
|
<Grid >
|
||||||
|
<custom:Modal Panel.ZIndex="1" IsOpen="{Binding IsModalOpen}">
|
||||||
|
<ContentControl Margin="50 25" Content="{Binding CurrentModalViewModel}"/>
|
||||||
|
</custom:Modal>
|
||||||
|
|
||||||
|
<views:YouTubeViewersView Margin="25" DataContext="{Binding YouTubeViewersViewModel}" />
|
||||||
|
</Grid>
|
||||||
|
</ScrollViewer>
|
||||||
|
</Window>
|
||||||
28
YouTubeViewers.WPF/MainWindow.xaml.cs
Normal file
28
YouTubeViewers.WPF/MainWindow.xaml.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Windows.Navigation;
|
||||||
|
using System.Windows.Shapes;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for MainWindow.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class MainWindow : Window
|
||||||
|
{
|
||||||
|
public MainWindow()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
28
YouTubeViewers.WPF/Stores/ModalNavigationStore.cs
Normal file
28
YouTubeViewers.WPF/Stores/ModalNavigationStore.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using YouTubeViewers.WPF.ViewModels;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.Stores
|
||||||
|
{
|
||||||
|
public class ModalNavigationStore
|
||||||
|
{
|
||||||
|
private ViewModelBase _currentViewModel;
|
||||||
|
|
||||||
|
public ViewModelBase CurrentViewModel
|
||||||
|
{
|
||||||
|
get { return _currentViewModel; }
|
||||||
|
set {
|
||||||
|
_currentViewModel = value;
|
||||||
|
CurrentViewModelChanged?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsOpen => CurrentViewModel != null;
|
||||||
|
|
||||||
|
public event Action CurrentViewModelChanged;
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
CurrentViewModel = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
43
YouTubeViewers.WPF/Stores/SelectedYouTubeViewerStore.cs
Normal file
43
YouTubeViewers.WPF/Stores/SelectedYouTubeViewerStore.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using YouTubeViewers.Domain.Models;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.Stores
|
||||||
|
{
|
||||||
|
public class SelectedYouTubeViewerStore
|
||||||
|
{
|
||||||
|
private readonly YouTubeViewersStore _youTubeViewersStore;
|
||||||
|
|
||||||
|
public SelectedYouTubeViewerStore(YouTubeViewersStore youTubeViewersStore)
|
||||||
|
{
|
||||||
|
_youTubeViewersStore = youTubeViewersStore;
|
||||||
|
_youTubeViewersStore.YouTubeViewerUpdated += YouTubeViewersStore_YouTubeViewerUpdated;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void YouTubeViewersStore_YouTubeViewerUpdated(YouTubeViewer youTubeViewer)
|
||||||
|
{
|
||||||
|
if (youTubeViewer.Id == SelectedYouTubeViewer?.Id)
|
||||||
|
{
|
||||||
|
SelectedYouTubeViewer = youTubeViewer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private YouTubeViewer _selectedYouTubeViewer;
|
||||||
|
|
||||||
|
public YouTubeViewer SelectedYouTubeViewer
|
||||||
|
{
|
||||||
|
get { return _selectedYouTubeViewer; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_selectedYouTubeViewer = value;
|
||||||
|
SelectedYouTubeViewerChanged?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Action SelectedYouTubeViewerChanged;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
88
YouTubeViewers.WPF/Stores/YouTubeViewersStore.cs
Normal file
88
YouTubeViewers.WPF/Stores/YouTubeViewersStore.cs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using YouTubeViewers.Domain.Commands;
|
||||||
|
using YouTubeViewers.Domain.Models;
|
||||||
|
using YouTubeViewers.Domain.Queries;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.Stores
|
||||||
|
{
|
||||||
|
public class YouTubeViewersStore
|
||||||
|
{
|
||||||
|
private readonly IGetAllYouTubeViewersQuery _getAllYouTubeViewersQuery;
|
||||||
|
private readonly ICreateYouTubeViewerCommand _createYouTubeViewerCommand;
|
||||||
|
private readonly IUpdateYouTubeViewerCommand _updateYouTubeViewerCommand;
|
||||||
|
private readonly IDeleteYouTubeViewerCommand _deleteYouTubeViewerCommand;
|
||||||
|
private readonly List<YouTubeViewer> _youTubeViewers;
|
||||||
|
|
||||||
|
public IEnumerable<YouTubeViewer> YouTubeViewers => _youTubeViewers;
|
||||||
|
|
||||||
|
public event Action YouTubeViewersLoaded;
|
||||||
|
public event Action<YouTubeViewer> YouTubeViewerAdded;
|
||||||
|
public event Action<YouTubeViewer> YouTubeViewerUpdated;
|
||||||
|
public event Action<Guid> YouTubeViewerDeleted;
|
||||||
|
|
||||||
|
|
||||||
|
public YouTubeViewersStore(
|
||||||
|
IGetAllYouTubeViewersQuery getAllYouTubeViewersQuery,
|
||||||
|
ICreateYouTubeViewerCommand createYouTubeViewerCommand,
|
||||||
|
IUpdateYouTubeViewerCommand updateYouTubeViewerCommand,
|
||||||
|
IDeleteYouTubeViewerCommand deleteYouTubeViewerCommand)
|
||||||
|
{
|
||||||
|
_getAllYouTubeViewersQuery = getAllYouTubeViewersQuery;
|
||||||
|
_createYouTubeViewerCommand = createYouTubeViewerCommand;
|
||||||
|
_updateYouTubeViewerCommand = updateYouTubeViewerCommand;
|
||||||
|
_deleteYouTubeViewerCommand = deleteYouTubeViewerCommand;
|
||||||
|
|
||||||
|
_youTubeViewers = new List<YouTubeViewer>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Load()
|
||||||
|
{
|
||||||
|
IEnumerable<YouTubeViewer> youTubeViewers = await _getAllYouTubeViewersQuery.Execute();
|
||||||
|
_youTubeViewers.Clear();
|
||||||
|
_youTubeViewers.AddRange(youTubeViewers);
|
||||||
|
|
||||||
|
YouTubeViewersLoaded?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Add(YouTubeViewer youTubeViewer)
|
||||||
|
{
|
||||||
|
await _createYouTubeViewerCommand.Execute(youTubeViewer);
|
||||||
|
|
||||||
|
_youTubeViewers.Add(youTubeViewer);
|
||||||
|
|
||||||
|
YouTubeViewerAdded?.Invoke(youTubeViewer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Update(YouTubeViewer youTubeViewer)
|
||||||
|
{
|
||||||
|
await _updateYouTubeViewerCommand.Execute(youTubeViewer);
|
||||||
|
|
||||||
|
int currentIndex = _youTubeViewers.FindIndex(y => y.Id == youTubeViewer.Id);
|
||||||
|
|
||||||
|
if(currentIndex != -1)
|
||||||
|
{
|
||||||
|
_youTubeViewers[currentIndex] = youTubeViewer;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_youTubeViewers.Add(youTubeViewer);
|
||||||
|
}
|
||||||
|
|
||||||
|
YouTubeViewerUpdated?.Invoke(youTubeViewer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Delete(Guid id)
|
||||||
|
{
|
||||||
|
await _deleteYouTubeViewerCommand.Execute(id);
|
||||||
|
|
||||||
|
_youTubeViewers.RemoveAll(y => y.Id == id);
|
||||||
|
|
||||||
|
YouTubeViewerDeleted?.Invoke(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
23
YouTubeViewers.WPF/ViewModels/AddYouTubeViewerViewModel.cs
Normal file
23
YouTubeViewers.WPF/ViewModels/AddYouTubeViewerViewModel.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using YouTubeViewers.WPF.Commands;
|
||||||
|
using YouTubeViewers.WPF.Stores;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.ViewModels;
|
||||||
|
|
||||||
|
public class AddYouTubeViewerViewModel : ViewModelBase
|
||||||
|
{
|
||||||
|
public YouTubeViewerDetailsFormViewModel YouTubeViewerDetailsFormViewModel { get; }
|
||||||
|
|
||||||
|
public AddYouTubeViewerViewModel(YouTubeViewersStore _youTubeViewersStore, ModalNavigationStore modalNavigationStore)
|
||||||
|
{
|
||||||
|
ICommand cancelCommand = new CloseModalCommand( modalNavigationStore);
|
||||||
|
ICommand submitCommand = new AddYouTubeViewerCommand(this , _youTubeViewersStore,modalNavigationStore);
|
||||||
|
YouTubeViewerDetailsFormViewModel = new YouTubeViewerDetailsFormViewModel(submitCommand,cancelCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
32
YouTubeViewers.WPF/ViewModels/EditYouTubeViewerViewModel.cs
Normal file
32
YouTubeViewers.WPF/ViewModels/EditYouTubeViewerViewModel.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using YouTubeViewers.WPF.Commands;
|
||||||
|
using YouTubeViewers.Domain.Models;
|
||||||
|
using YouTubeViewers.WPF.Stores;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.ViewModels;
|
||||||
|
|
||||||
|
public class EditYouTubeViewerViewModel : ViewModelBase
|
||||||
|
{
|
||||||
|
public Guid YouTubeViewerId { get; }
|
||||||
|
|
||||||
|
public YouTubeViewerDetailsFormViewModel YouTubeViewerDetailsFormViewModel { get; }
|
||||||
|
|
||||||
|
public EditYouTubeViewerViewModel(YouTubeViewer youTubeViewer, YouTubeViewersStore _youTubeViewersStore, ModalNavigationStore modalNavigationStore)
|
||||||
|
{
|
||||||
|
YouTubeViewerId = youTubeViewer.Id;
|
||||||
|
|
||||||
|
ICommand submitCommand = new EditYouTubeViewerCommand(this, _youTubeViewersStore, modalNavigationStore);
|
||||||
|
ICommand cancelCommand = new CloseModalCommand(modalNavigationStore);
|
||||||
|
YouTubeViewerDetailsFormViewModel = new YouTubeViewerDetailsFormViewModel(submitCommand, cancelCommand)
|
||||||
|
{
|
||||||
|
UserName = youTubeViewer.Username,
|
||||||
|
IsSubScribed = youTubeViewer.IsSubscribed,
|
||||||
|
IsMember = youTubeViewer.IsMember
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
38
YouTubeViewers.WPF/ViewModels/MainViewModel.cs
Normal file
38
YouTubeViewers.WPF/ViewModels/MainViewModel.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using YouTubeViewers.WPF.Stores;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.ViewModels
|
||||||
|
{
|
||||||
|
public class MainViewModel : ViewModelBase
|
||||||
|
{
|
||||||
|
private readonly ModalNavigationStore _modalNavigationStore;
|
||||||
|
|
||||||
|
public ViewModelBase CurrentModalViewModel => _modalNavigationStore.CurrentViewModel;
|
||||||
|
public bool IsModalOpen => _modalNavigationStore.IsOpen;
|
||||||
|
public YouTubeViewersViewModel YouTubeViewersViewModel { get; }
|
||||||
|
|
||||||
|
public MainViewModel(ModalNavigationStore modalNavigationStore, YouTubeViewersViewModel youTubeViewersViewModel)
|
||||||
|
{
|
||||||
|
_modalNavigationStore = modalNavigationStore;
|
||||||
|
YouTubeViewersViewModel = youTubeViewersViewModel;
|
||||||
|
|
||||||
|
_modalNavigationStore.CurrentViewModelChanged += ModalNavigationStore_CurrenyViewModelChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose()
|
||||||
|
{
|
||||||
|
_modalNavigationStore.CurrentViewModelChanged -= ModalNavigationStore_CurrenyViewModelChanged;
|
||||||
|
base.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ModalNavigationStore_CurrenyViewModelChanged()
|
||||||
|
{
|
||||||
|
OnPropertyChanged(nameof(CurrentModalViewModel));
|
||||||
|
OnPropertyChanged(nameof(IsModalOpen));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
YouTubeViewers.WPF/ViewModels/ViewModelBase.cs
Normal file
22
YouTubeViewers.WPF/ViewModels/ViewModelBase.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.ViewModels
|
||||||
|
{
|
||||||
|
public class ViewModelBase : INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
public event PropertyChangedEventHandler? PropertyChanged;
|
||||||
|
|
||||||
|
protected virtual void OnPropertyChanged(string propertyName = null)
|
||||||
|
{
|
||||||
|
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose() { }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,71 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Input;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.ViewModels;
|
||||||
|
|
||||||
|
public class YouTubeViewerDetailsFormViewModel : ViewModelBase
|
||||||
|
{
|
||||||
|
private string _userName;
|
||||||
|
|
||||||
|
public string UserName
|
||||||
|
{
|
||||||
|
get { return _userName; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_userName = value;
|
||||||
|
OnPropertyChanged(nameof(UserName));
|
||||||
|
OnPropertyChanged(nameof(CanSubmit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _isSubScribed;
|
||||||
|
|
||||||
|
public bool IsSubScribed
|
||||||
|
{
|
||||||
|
get { return _isSubScribed; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_isSubScribed = value;
|
||||||
|
OnPropertyChanged(nameof(IsSubScribed));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _isMember;
|
||||||
|
|
||||||
|
|
||||||
|
public bool IsMember
|
||||||
|
{
|
||||||
|
get { return _isMember; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_isMember = value;
|
||||||
|
OnPropertyChanged(nameof(IsMember));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region IsSubmitting
|
||||||
|
|
||||||
|
private bool _IsSubmitting;
|
||||||
|
public bool IsSubmitting
|
||||||
|
{
|
||||||
|
get { return _IsSubmitting; }
|
||||||
|
set { _IsSubmitting = value; OnPropertyChanged(nameof(IsSubmitting)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion IsSubmitting
|
||||||
|
|
||||||
|
public bool CanSubmit => !string.IsNullOrEmpty(UserName);
|
||||||
|
public ICommand SubmitCommand { get; }
|
||||||
|
public ICommand CancelCommand { get; }
|
||||||
|
public YouTubeViewerDetailsFormViewModel(ICommand submitCommand, ICommand cancelCommand)
|
||||||
|
{
|
||||||
|
SubmitCommand = submitCommand;
|
||||||
|
CancelCommand = cancelCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using YouTubeViewers.WPF.Stores;
|
||||||
|
using YouTubeViewers.Domain.Models;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.ViewModels
|
||||||
|
{
|
||||||
|
public class YouTubeViewersDetailsViewModel : ViewModelBase
|
||||||
|
{
|
||||||
|
private readonly SelectedYouTubeViewerStore _selectedYouTubeViewerStore;
|
||||||
|
private YouTubeViewer SelectedYouTubeViewer => _selectedYouTubeViewerStore.SelectedYouTubeViewer;
|
||||||
|
|
||||||
|
public bool HasSelectedYouTubeViewer => SelectedYouTubeViewer != null;
|
||||||
|
public string UserName => SelectedYouTubeViewer?.Username ?? "Unknown";
|
||||||
|
public string IsSubScribedDisplay => (SelectedYouTubeViewer?.IsSubscribed ?? false) ? "Yes" : "No";
|
||||||
|
public string IsMemberDisplay => (SelectedYouTubeViewer?.IsMember ?? false) ? "Yes" : "No";
|
||||||
|
|
||||||
|
public YouTubeViewersDetailsViewModel(SelectedYouTubeViewerStore selectedYouTubeViewerStore)
|
||||||
|
{
|
||||||
|
_selectedYouTubeViewerStore = selectedYouTubeViewerStore;
|
||||||
|
|
||||||
|
_selectedYouTubeViewerStore.SelectedYouTubeViewerChanged += SelectedYouTubeViewerStore_SelectedYouTubeViewerChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose()
|
||||||
|
{
|
||||||
|
_selectedYouTubeViewerStore.SelectedYouTubeViewerChanged -= SelectedYouTubeViewerStore_SelectedYouTubeViewerChanged;
|
||||||
|
base.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SelectedYouTubeViewerStore_SelectedYouTubeViewerChanged()
|
||||||
|
{
|
||||||
|
OnPropertyChanged(nameof(HasSelectedYouTubeViewer));
|
||||||
|
OnPropertyChanged(nameof(UserName));
|
||||||
|
OnPropertyChanged(nameof(IsSubScribedDisplay));
|
||||||
|
OnPropertyChanged(nameof(IsMemberDisplay));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using YouTubeViewers.WPF.Commands;
|
||||||
|
using YouTubeViewers.Domain.Models;
|
||||||
|
using YouTubeViewers.WPF.Stores;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.ViewModels
|
||||||
|
{
|
||||||
|
public class YouTubeViewersListingItemViewModel : ViewModelBase
|
||||||
|
{
|
||||||
|
//private YouTubeViewer _youTubeViewer;
|
||||||
|
//private YouTubeViewersStore _youTubeViewersStore;
|
||||||
|
//private ModalNavigationStore _modalNavigationStore;
|
||||||
|
|
||||||
|
public YouTubeViewer YouTubeViewer { get; private set; }
|
||||||
|
|
||||||
|
public string UserName => YouTubeViewer.Username;
|
||||||
|
|
||||||
|
public ICommand EditCommand { get; }
|
||||||
|
public ICommand DeleteCommand { get; }
|
||||||
|
|
||||||
|
public YouTubeViewersListingItemViewModel(YouTubeViewer youTubeViewer, YouTubeViewersStore youTubeViewersStore, ModalNavigationStore modalNavigationStore)
|
||||||
|
{
|
||||||
|
YouTubeViewer = youTubeViewer;
|
||||||
|
|
||||||
|
EditCommand = new OpenEditYouTubeViewerCommand(this, youTubeViewersStore, modalNavigationStore);
|
||||||
|
DeleteCommand = new DeleteYouTubeViewerCommand(this, youTubeViewersStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(YouTubeViewer youTubeViewer)
|
||||||
|
{
|
||||||
|
YouTubeViewer = youTubeViewer;
|
||||||
|
OnPropertyChanged(nameof(UserName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
111
YouTubeViewers.WPF/ViewModels/YouTubeViewersListingViewModel.cs
Normal file
111
YouTubeViewers.WPF/ViewModels/YouTubeViewersListingViewModel.cs
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using YouTubeViewers.WPF.Commands;
|
||||||
|
using YouTubeViewers.Domain.Models;
|
||||||
|
using YouTubeViewers.WPF.Stores;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.ViewModels
|
||||||
|
{
|
||||||
|
public class YouTubeViewersListingViewModel : ViewModelBase
|
||||||
|
{
|
||||||
|
private readonly ObservableCollection<YouTubeViewersListingItemViewModel> _youtubeViewersListingItemViewModels;
|
||||||
|
private readonly YouTubeViewersStore _youTubeViewersStore;
|
||||||
|
private readonly SelectedYouTubeViewerStore _selectedYouTubeViewerStore;
|
||||||
|
private readonly ModalNavigationStore _modalNavigationStore;
|
||||||
|
|
||||||
|
public IEnumerable<YouTubeViewersListingItemViewModel> YouTubeViewersListingItemViewModels => _youtubeViewersListingItemViewModels;
|
||||||
|
|
||||||
|
private YouTubeViewersListingItemViewModel _selectedYouTubeViewerListingItemViewModel;
|
||||||
|
|
||||||
|
public YouTubeViewersListingItemViewModel SelectedYouTubeViewerListingItemViewModel
|
||||||
|
{
|
||||||
|
get { return _selectedYouTubeViewerListingItemViewModel; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_selectedYouTubeViewerListingItemViewModel = value;
|
||||||
|
OnPropertyChanged(nameof(SelectedYouTubeViewerListingItemViewModel));
|
||||||
|
_selectedYouTubeViewerStore.SelectedYouTubeViewer = _selectedYouTubeViewerListingItemViewModel?.YouTubeViewer;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public YouTubeViewersListingViewModel(
|
||||||
|
YouTubeViewersStore youTubeViewersStore,
|
||||||
|
SelectedYouTubeViewerStore selectedYouTubeViewerStore,
|
||||||
|
ModalNavigationStore modalNavigationStore)
|
||||||
|
{
|
||||||
|
_youTubeViewersStore = youTubeViewersStore;
|
||||||
|
_selectedYouTubeViewerStore = selectedYouTubeViewerStore;
|
||||||
|
_modalNavigationStore = modalNavigationStore;
|
||||||
|
_youtubeViewersListingItemViewModels = new ObservableCollection<YouTubeViewersListingItemViewModel>();
|
||||||
|
|
||||||
|
|
||||||
|
_youTubeViewersStore.YouTubeViewersLoaded += _youTubeViewersStore_YouTubeViewersLoaded;
|
||||||
|
_youTubeViewersStore.YouTubeViewerAdded += YouTubeViewersStore_YouTubeViewerAdded;
|
||||||
|
_youTubeViewersStore.YouTubeViewerUpdated += YouTubeViewersStore_YouTubeViewerUpdated;
|
||||||
|
_youTubeViewersStore.YouTubeViewerDeleted += YouTubeViewersStore_YouTubeViewerDeleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void _youTubeViewersStore_YouTubeViewersLoaded()
|
||||||
|
{
|
||||||
|
_youtubeViewersListingItemViewModels.Clear();
|
||||||
|
foreach (YouTubeViewer youTubeViewer in _youTubeViewersStore.YouTubeViewers)
|
||||||
|
{
|
||||||
|
AddYouTubeViewer(youTubeViewer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void YouTubeViewersStore_YouTubeViewerUpdated(YouTubeViewer youTubeViewer)
|
||||||
|
{
|
||||||
|
YouTubeViewersListingItemViewModel youTubeViewerViewModel =
|
||||||
|
_youtubeViewersListingItemViewModels.FirstOrDefault(x => x.YouTubeViewer.Id == youTubeViewer.Id);
|
||||||
|
|
||||||
|
if (youTubeViewerViewModel != null)
|
||||||
|
{
|
||||||
|
youTubeViewerViewModel.Update(youTubeViewer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected override void Dispose()
|
||||||
|
{
|
||||||
|
_youTubeViewersStore.YouTubeViewersLoaded -= _youTubeViewersStore_YouTubeViewersLoaded;
|
||||||
|
_youTubeViewersStore.YouTubeViewerAdded -= YouTubeViewersStore_YouTubeViewerAdded;
|
||||||
|
_youTubeViewersStore.YouTubeViewerUpdated -= YouTubeViewersStore_YouTubeViewerUpdated;
|
||||||
|
_youTubeViewersStore.YouTubeViewerDeleted -= YouTubeViewersStore_YouTubeViewerDeleted;
|
||||||
|
|
||||||
|
base.Dispose();
|
||||||
|
}
|
||||||
|
private void YouTubeViewersStore_YouTubeViewerAdded(YouTubeViewer youTubeViewer)
|
||||||
|
{
|
||||||
|
AddYouTubeViewer(youTubeViewer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddYouTubeViewer(YouTubeViewer youTubeViewer)
|
||||||
|
{
|
||||||
|
YouTubeViewersListingItemViewModel itemViewModel =
|
||||||
|
new YouTubeViewersListingItemViewModel(youTubeViewer, _youTubeViewersStore, _modalNavigationStore);
|
||||||
|
_youtubeViewersListingItemViewModels.Add(itemViewModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void YouTubeViewersStore_YouTubeViewerDeleted(Guid id)
|
||||||
|
{
|
||||||
|
YouTubeViewersListingItemViewModel itemViewModel = _youtubeViewersListingItemViewModels.FirstOrDefault(y => y.YouTubeViewer?.Id == id);
|
||||||
|
|
||||||
|
if (itemViewModel != null)
|
||||||
|
{
|
||||||
|
_youtubeViewersListingItemViewModels.Remove(itemViewModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
55
YouTubeViewers.WPF/ViewModels/YouTubeViewersViewModel.cs
Normal file
55
YouTubeViewers.WPF/ViewModels/YouTubeViewersViewModel.cs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using YouTubeViewers.WPF.Commands;
|
||||||
|
using YouTubeViewers.WPF.Stores;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.ViewModels
|
||||||
|
{
|
||||||
|
public class YouTubeViewersViewModel : ViewModelBase
|
||||||
|
{
|
||||||
|
public YouTubeViewersListingViewModel YouTubeViewersListingViewModel { get; }
|
||||||
|
public YouTubeViewersDetailsViewModel YouTubeViewersDetailsViewModel { get; }
|
||||||
|
|
||||||
|
|
||||||
|
private bool _IsLoading;
|
||||||
|
public bool IsLoading
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _IsLoading;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_IsLoading = value;
|
||||||
|
OnPropertyChanged(nameof(IsLoading));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICommand LoadYouTubeViewersCommand { get; }
|
||||||
|
public ICommand AddYouTubeViewersCommand { get; }
|
||||||
|
public YouTubeViewersViewModel(YouTubeViewersStore youTubeViewersStore, SelectedYouTubeViewerStore _selectedYouTubeViewerStore, ModalNavigationStore modalNavigationStore)
|
||||||
|
{
|
||||||
|
|
||||||
|
YouTubeViewersListingViewModel = new YouTubeViewersListingViewModel(youTubeViewersStore, _selectedYouTubeViewerStore, modalNavigationStore);
|
||||||
|
YouTubeViewersDetailsViewModel = new YouTubeViewersDetailsViewModel(_selectedYouTubeViewerStore);
|
||||||
|
LoadYouTubeViewersCommand = new LoadYouTubeViewersCommand(this,youTubeViewersStore);
|
||||||
|
AddYouTubeViewersCommand = new OpenAddYouTubeViewerCommand(youTubeViewersStore, modalNavigationStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static YouTubeViewersViewModel LoadViewModel(
|
||||||
|
YouTubeViewersStore youTubeViewersStore,
|
||||||
|
SelectedYouTubeViewerStore selectedYouTubeViewerStore,
|
||||||
|
ModalNavigationStore modalNavigationStore)
|
||||||
|
{
|
||||||
|
YouTubeViewersViewModel viewModel = new YouTubeViewersViewModel(youTubeViewersStore, selectedYouTubeViewerStore, modalNavigationStore);
|
||||||
|
|
||||||
|
viewModel.LoadYouTubeViewersCommand.Execute(null);
|
||||||
|
|
||||||
|
return viewModel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
YouTubeViewers.WPF/Views/AddYouTubeViewerView.xaml
Normal file
26
YouTubeViewers.WPF/Views/AddYouTubeViewerView.xaml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<UserControl x:Class="YouTubeViewers.WPF.Views.AddYouTubeViewerView"
|
||||||
|
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:YouTubeViewers.WPF.Views"
|
||||||
|
xmlns:components="clr-namespace:YouTubeViewers.WPF.Components"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="auto"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="0"
|
||||||
|
Style="{StaticResource PageHeader}"
|
||||||
|
Text="Add YouTube Viewers" />
|
||||||
|
|
||||||
|
<components:YouTubeViewerDetailsForm Grid.Row="1" Margin="0 30 0 0 " DataContext="{Binding YouTubeViewerDetailsFormViewModel}"/>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
|
|
||||||
|
|
||||||
28
YouTubeViewers.WPF/Views/AddYouTubeViewerView.xaml.cs
Normal file
28
YouTubeViewers.WPF/Views/AddYouTubeViewerView.xaml.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Windows.Navigation;
|
||||||
|
using System.Windows.Shapes;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.Views
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for AddYouTubeViewerView.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class AddYouTubeViewerView : UserControl
|
||||||
|
{
|
||||||
|
public AddYouTubeViewerView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
YouTubeViewers.WPF/Views/EditYouTubeViewerView.xaml
Normal file
24
YouTubeViewers.WPF/Views/EditYouTubeViewerView.xaml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<UserControl x:Class="YouTubeViewers.WPF.Views.EditYouTubeViewerView"
|
||||||
|
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:YouTubeViewers.WPF.Views"
|
||||||
|
xmlns:components="clr-namespace:YouTubeViewers.WPF.Components"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="auto"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="0"
|
||||||
|
Style="{StaticResource PageHeader}"
|
||||||
|
Text="Edit YouTube Viewers" />
|
||||||
|
|
||||||
|
<components:YouTubeViewerDetailsForm Grid.Row="1" Margin="0 30 0 0 " DataContext="{Binding YouTubeViewerDetailsFormViewModel}"/>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
28
YouTubeViewers.WPF/Views/EditYouTubeViewerView.xaml.cs
Normal file
28
YouTubeViewers.WPF/Views/EditYouTubeViewerView.xaml.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Windows.Navigation;
|
||||||
|
using System.Windows.Shapes;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.Views
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for EditYouTubeViewerView.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class EditYouTubeViewerView : UserControl
|
||||||
|
{
|
||||||
|
public EditYouTubeViewerView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
59
YouTubeViewers.WPF/Views/YouTubeViewersView.xaml
Normal file
59
YouTubeViewers.WPF/Views/YouTubeViewersView.xaml
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<UserControl x:Class="YouTubeViewers.WPF.Views.YouTubeViewersView"
|
||||||
|
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:YouTubeViewers.WPF.Views"
|
||||||
|
xmlns:components="clr-namespace:YouTubeViewers.WPF.Components"
|
||||||
|
xmlns:custom="clr-namespace:LoadingSpinnerControl;assembly=LoadingSpinnerControl"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
|
<Grid>
|
||||||
|
<StackPanel VerticalAlignment="Center">
|
||||||
|
<StackPanel.Style>
|
||||||
|
<Style TargetType="StackPanel">
|
||||||
|
<Setter Property="Visibility" Value="Collapsed"/>
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding IsLoading}" Value="true">
|
||||||
|
<Setter Property="Visibility" Value="Visible"/>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</StackPanel.Style>
|
||||||
|
<custom:LoadingSpinner Diameter="100" IsLoading="True" Thickness="3"/>
|
||||||
|
<TextBlock Margin="0 10 0 0" Text="Loading YouTube Viewers..." TextAlignment="Center" />
|
||||||
|
</StackPanel>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Style>
|
||||||
|
<Style TargetType="Grid">
|
||||||
|
<Setter Property="Visibility" Value="Collapsed"/>
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding IsLoading}" Value="false">
|
||||||
|
<Setter Property="Visibility" Value="Visible"/>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</Grid.Style>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid Grid.Row="0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Grid.Column="0" Style="{StaticResource PageHeader}" Text="YouTube Viewers" />
|
||||||
|
<Button Grid.Column="1" Content="Add" FontSize="16" Command="{Binding AddYouTubeViewersCommand}"/>
|
||||||
|
</Grid>
|
||||||
|
<Grid Grid.Row="1" Margin="0 20 0 0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="2*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<components:YouTubeViewersListing Grid.Column="0" DataContext="{Binding YouTubeViewersListingViewModel}"/>
|
||||||
|
<components:YouTubeViewersDetails Grid.Column="1" Margin="20 0 0 0" DataContext="{Binding YouTubeViewersDetailsViewModel}"/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
28
YouTubeViewers.WPF/Views/YouTubeViewersView.xaml.cs
Normal file
28
YouTubeViewers.WPF/Views/YouTubeViewersView.xaml.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Windows.Navigation;
|
||||||
|
using System.Windows.Shapes;
|
||||||
|
|
||||||
|
namespace YouTubeViewers.WPF.Views
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for YouTubeViewersView.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class YouTubeViewersView : UserControl
|
||||||
|
{
|
||||||
|
public YouTubeViewersView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
YouTubeViewers.WPF/YouTubeViewers.WPF.csproj
Normal file
21
YouTubeViewers.WPF/YouTubeViewers.WPF.csproj
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<TargetFramework>net6.0-windows</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<UseWPF>true</UseWPF>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="DropdownMenu.WPF" Version="1.0.0" />
|
||||||
|
<PackageReference Include="LoadingSpinner.WPF" Version="1.0.0" />
|
||||||
|
<PackageReference Include="SimpleModal.WPF" Version="1.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\YouTubeViewers.Domain\YouTubeViewers.Domain.csproj" />
|
||||||
|
<ProjectReference Include="..\YouTubeViewers.EntityFramework\YouTubeViewers.EntityFramework.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
37
YouTubeViewers.sln
Normal file
37
YouTubeViewers.sln
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.2.32630.192
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YouTubeViewers.WPF", "YouTubeViewers.WPF\YouTubeViewers.WPF.csproj", "{679DDC1B-2FA6-42C0-B910-A6712C0E5855}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YouTubeViewers.EntityFramework", "YouTubeViewers.EntityFramework\YouTubeViewers.EntityFramework.csproj", "{5AF69F2E-1B26-4EC0-B4BC-68E82D22A951}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YouTubeViewers.Domain", "YouTubeViewers.Domain\YouTubeViewers.Domain.csproj", "{98B6551C-821E-4F94-8596-FD51ABC486EC}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{679DDC1B-2FA6-42C0-B910-A6712C0E5855}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{679DDC1B-2FA6-42C0-B910-A6712C0E5855}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{679DDC1B-2FA6-42C0-B910-A6712C0E5855}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{679DDC1B-2FA6-42C0-B910-A6712C0E5855}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{5AF69F2E-1B26-4EC0-B4BC-68E82D22A951}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{5AF69F2E-1B26-4EC0-B4BC-68E82D22A951}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{5AF69F2E-1B26-4EC0-B4BC-68E82D22A951}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{5AF69F2E-1B26-4EC0-B4BC-68E82D22A951}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{98B6551C-821E-4F94-8596-FD51ABC486EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{98B6551C-821E-4F94-8596-FD51ABC486EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{98B6551C-821E-4F94-8596-FD51ABC486EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{98B6551C-821E-4F94-8596-FD51ABC486EC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {2C2C9C21-98B7-408C-BFA3-B942E31D21AA}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
Reference in New Issue
Block a user