Add starter project for chapter 4

This commit is contained in:
Alvin Ashcraft
2023-05-29 11:43:34 -04:00
parent 5ec4e6e6b4
commit e512a9926c
25 changed files with 861 additions and 0 deletions
+43
View File
@@ -0,0 +1,43 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.33530.505
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyMediaCollection", "MyMediaCollection\MyMediaCollection.csproj", "{972D5C0D-86E6-4A2F-A6FD-8D4FE3380707}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{972D5C0D-86E6-4A2F-A6FD-8D4FE3380707}.Debug|ARM64.ActiveCfg = Debug|ARM64
{972D5C0D-86E6-4A2F-A6FD-8D4FE3380707}.Debug|ARM64.Build.0 = Debug|ARM64
{972D5C0D-86E6-4A2F-A6FD-8D4FE3380707}.Debug|ARM64.Deploy.0 = Debug|ARM64
{972D5C0D-86E6-4A2F-A6FD-8D4FE3380707}.Debug|x64.ActiveCfg = Debug|x64
{972D5C0D-86E6-4A2F-A6FD-8D4FE3380707}.Debug|x64.Build.0 = Debug|x64
{972D5C0D-86E6-4A2F-A6FD-8D4FE3380707}.Debug|x64.Deploy.0 = Debug|x64
{972D5C0D-86E6-4A2F-A6FD-8D4FE3380707}.Debug|x86.ActiveCfg = Debug|x86
{972D5C0D-86E6-4A2F-A6FD-8D4FE3380707}.Debug|x86.Build.0 = Debug|x86
{972D5C0D-86E6-4A2F-A6FD-8D4FE3380707}.Debug|x86.Deploy.0 = Debug|x86
{972D5C0D-86E6-4A2F-A6FD-8D4FE3380707}.Release|ARM64.ActiveCfg = Release|ARM64
{972D5C0D-86E6-4A2F-A6FD-8D4FE3380707}.Release|ARM64.Build.0 = Release|ARM64
{972D5C0D-86E6-4A2F-A6FD-8D4FE3380707}.Release|ARM64.Deploy.0 = Release|ARM64
{972D5C0D-86E6-4A2F-A6FD-8D4FE3380707}.Release|x64.ActiveCfg = Release|x64
{972D5C0D-86E6-4A2F-A6FD-8D4FE3380707}.Release|x64.Build.0 = Release|x64
{972D5C0D-86E6-4A2F-A6FD-8D4FE3380707}.Release|x64.Deploy.0 = Release|x64
{972D5C0D-86E6-4A2F-A6FD-8D4FE3380707}.Release|x86.ActiveCfg = Release|x86
{972D5C0D-86E6-4A2F-A6FD-8D4FE3380707}.Release|x86.Build.0 = Release|x86
{972D5C0D-86E6-4A2F-A6FD-8D4FE3380707}.Release|x86.Deploy.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C9277197-C949-4948-80CD-0A685EE6DCBB}
EndGlobalSection
EndGlobal
@@ -0,0 +1,18 @@
<!-- Copyright (c) Microsoft Corporation and Contributors. -->
<!-- Licensed under the MIT License. -->
<Application
x:Class="MyMediaCollection.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyMediaCollection">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<!-- Other merged dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<!-- Other app resources here -->
</ResourceDictionary>
</Application.Resources>
</Application>
@@ -0,0 +1,34 @@
using Microsoft.UI.Xaml;
using MyMediaCollection.ViewModels;
namespace MyMediaCollection
{
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
public partial class App : Application
{
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
this.InitializeComponent();
}
public static MainViewModel ViewModel { get; } = new MainViewModel();
/// <summary>
/// Invoked when the application is launched.
/// </summary>
/// <param name="args">Details about the launch request and process.</param>
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
m_window = new MainWindow();
m_window.Activate();
}
private Window m_window;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

@@ -0,0 +1,9 @@
namespace MyMediaCollection.Enums
{
public enum ItemType
{
Music,
Video,
Book
}
}
@@ -0,0 +1,8 @@
namespace MyMediaCollection.Enums
{
public enum LocationType
{
InCollection,
Loaned
}
}
@@ -0,0 +1,78 @@
<!-- Copyright (c) Microsoft Corporation and Contributors. -->
<!-- Licensed under the MIT License. -->
<Window
x:Class="MyMediaCollection.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyMediaCollection"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:model="using:MyMediaCollection.Model"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Media Collection" Margin="4" FontWeight="Bold" VerticalAlignment="Center"/>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
<TextBlock Text="Media Type:" Margin="4" FontWeight="Bold" VerticalAlignment="Center"/>
<ComboBox ItemsSource="{x:Bind ViewModel.Mediums}" SelectedItem="{x:Bind ViewModel.SelectedMedium, Mode=TwoWay}" MinWidth="120" Margin="0,2,6,4"/>
</StackPanel>
</Grid>
<ListView Grid.Row="1" ItemsSource="{x:Bind ViewModel.Items}" SelectedItem="{x:Bind ViewModel.SelectedMediaItem, Mode=TwoWay}">
<ListView.HeaderTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border BorderBrush="BlueViolet" BorderThickness="0,0,0,1">
<TextBlock Text="Medium" Margin="5,0,0,0" FontWeight="Bold"/>
</Border>
<Border Grid.Column="1" BorderBrush="BlueViolet" BorderThickness="0,0,0,1">
<TextBlock Text="Title" Margin="5,0,0,0" FontWeight="Bold"/>
</Border>
</Grid>
</DataTemplate>
</ListView.HeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate x:DataType="model:MediaItem">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{x:Bind Path=MediumInfo.Name, Mode=TwoWay}"/>
<TextBlock Grid.Column="1" Text="{x:Bind Path=Name}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackPanel Grid.Row="2"
HorizontalAlignment="Right"
Orientation="Horizontal">
<Button Command="{x:Bind ViewModel.AddEditCommand}"
Content="Add Item"
Margin="8,8,0,8"/>
<Button Command="{x:Bind ViewModel.DeleteCommand}"
Content="Delete Item"
Margin="8"/>
</StackPanel>
</Grid>
</Window>
@@ -0,0 +1,18 @@
using Microsoft.UI.Xaml;
using MyMediaCollection.ViewModels;
namespace MyMediaCollection
{
/// <summary>
/// An empty window that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
}
public MainViewModel ViewModel => App.ViewModel;
}
}
@@ -0,0 +1,13 @@
using MyMediaCollection.Enums;
namespace MyMediaCollection.Model
{
public class MediaItem
{
public int Id { get; set; }
public string Name { get; set; }
public ItemType MediaType { get; set; }
public Medium MediumInfo { get; set; }
public LocationType Location { get; set; }
}
}
@@ -0,0 +1,11 @@
using MyMediaCollection.Enums;
namespace MyMediaCollection.Model
{
public class Medium
{
public int Id { get; set; }
public string Name { get; set; }
public ItemType MediaType { get; set; }
}
}
@@ -0,0 +1,49 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<RootNamespace>MyMediaCollection</RootNamespace>
<ApplicationManifest>app.manifest</ApplicationManifest>
<Platforms>x86;x64;ARM64</Platforms>
<RuntimeIdentifiers>win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers>
<PublishProfile>win10-$(Platform).pubxml</PublishProfile>
<UseWinUI>true</UseWinUI>
<EnableMsixTooling>true</EnableMsixTooling>
</PropertyGroup>
<ItemGroup>
<Content Include="Assets\SplashScreen.scale-200.png" />
<Content Include="Assets\LockScreenLogo.scale-200.png" />
<Content Include="Assets\Square150x150Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
<Content Include="Assets\StoreLogo.png" />
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.0" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.2.221109.1" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.755" />
<Manifest Include="$(ApplicationManifest)" />
</ItemGroup>
<!--
Defining the "Msix" ProjectCapability here allows the Single-project MSIX Packaging
Tools extension to be activated for this project even if the Windows App SDK Nuget
package has not yet been restored.
-->
<ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
<ProjectCapability Include="Msix" />
</ItemGroup>
<!--
Defining the "HasPackageAndPublishMenuAddedByProject" property here allows the Solution
Explorer "Package and Publish" context menu entry to be enabled for this project even if
the Windows App SDK Nuget package has not yet been restored.
-->
<PropertyGroup Condition="'$(DisableHasPackageAndPublishMenuAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
<HasPackageAndPublishMenu>true</HasPackageAndPublishMenu>
</PropertyGroup>
</Project>
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap rescap">
<Identity
Name="9457558b-77d0-43f9-b1e4-e6aa9aba05d6"
Publisher="CN=alash"
Version="1.0.0.0" />
<Properties>
<DisplayName>MyMediaCollection</DisplayName>
<PublisherDisplayName>alash</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="$targetentrypoint$">
<uap:VisualElements
DisplayName="MyMediaCollection"
Description="MyMediaCollection"
BackgroundColor="transparent"
Square150x150Logo="Assets\Square150x150Logo.png"
Square44x44Logo="Assets\Square44x44Logo.png">
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" />
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<rescap:Capability Name="runFullTrust" />
</Capabilities>
</Package>
@@ -0,0 +1,10 @@
{
"profiles": {
"MyMediaCollection (Package)": {
"commandName": "MsixPackage"
},
"MyMediaCollection (Unpackaged)": {
"commandName": "Project"
}
}
}
@@ -0,0 +1,28 @@
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace MyMediaCollection.ViewModels
{
public class BindableBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetProperty<T>(ref T originalValue, T newValue, [CallerMemberName] string propertyName = null)
{
if (Equals(originalValue, newValue))
{
return false;
}
originalValue = newValue;
OnPropertyChanged(propertyName);
return true;
}
}
}
@@ -0,0 +1,123 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using MyMediaCollection.Enums;
using MyMediaCollection.Model;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows.Input;
namespace MyMediaCollection.ViewModels
{
public partial class MainViewModel : ObservableObject
{
[ObservableProperty]
private string selectedMedium;
[ObservableProperty]
private ObservableCollection<MediaItem> items;
[ObservableProperty]
private IList<string> mediums;
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(DeleteCommand))]
private MediaItem selectedMediaItem;
private ObservableCollection<MediaItem> allItems;
private int additionalItemCount = 1;
public MainViewModel()
{
PopulateData();
}
public void PopulateData()
{
var cd = new MediaItem
{
Id = 1,
Name = "Classical Favorites",
MediaType = ItemType.Music,
MediumInfo = new Medium { Id = 1, MediaType = ItemType.Music, Name = "CD" }
};
var book = new MediaItem
{
Id = 2,
Name = "Classic Fairy Tales",
MediaType = ItemType.Book,
MediumInfo = new Medium { Id = 2, MediaType = ItemType.Book, Name = "Book" }
};
var bluRay = new MediaItem
{
Id = 3,
Name = "The Mummy",
MediaType = ItemType.Video,
MediumInfo = new Medium { Id = 3, MediaType = ItemType.Video, Name = "Blu Ray" }
};
Items = new ObservableCollection<MediaItem>
{
cd,
book,
bluRay
};
allItems = new ObservableCollection<MediaItem>(Items);
Mediums = new List<string>
{
"All",
nameof(ItemType.Book),
nameof(ItemType.Music),
nameof(ItemType.Video)
};
SelectedMedium = Mediums[0];
}
partial void OnSelectedMediumChanged(string value)
{
Items.Clear();
foreach (var item in allItems)
{
if (string.IsNullOrWhiteSpace(value) ||
value == "All" ||
value == item.MediaType.ToString())
{
Items.Add(item);
}
}
}
[RelayCommand]
public void AddEdit()
{
// Note this is temporary until
// we use a real data source for items.
const int startingItemCount = 3;
var newItem = new MediaItem
{
Id = startingItemCount + additionalItemCount,
Location = LocationType.InCollection,
MediaType = ItemType.Music,
MediumInfo = new Medium { Id = 1, MediaType = ItemType.Music, Name = "CD" },
Name = $"CD {additionalItemCount}"
};
allItems.Add(newItem);
Items.Add(newItem);
additionalItemCount++;
}
[RelayCommand(CanExecute = nameof(CanDeleteItem))]
public void Delete()
{
allItems.Remove(SelectedMediaItem);
Items.Remove(SelectedMediaItem);
}
private bool CanDeleteItem() => SelectedMediaItem != null;
}
}
@@ -0,0 +1,148 @@
using MyMediaCollection.Enums;
using MyMediaCollection.Model;
using System.Collections.Generic;
namespace MyMediaCollection.ViewModels
{
public class MainViewModel : BindableBase
{
private string selectedMedium;
private ObservableCollection<MediaItem> items;
private ObservableCollection<MediaItem> allItems;
private IList<string> mediums;
private MediaItem selectedMediaItem;
private int additionalItemCount = 1;
public MainViewModel()
{
PopulateData();
}
public void PopulateData()
{
var cd = new MediaItem
{
Id = 1,
Name = "Classical Favorites",
MediaType = ItemType.Music,
MediumInfo = new Medium { Id = 1, MediaType = ItemType.Music, Name = "CD" }
};
var book = new MediaItem
{
Id = 2,
Name = "Classic Fairy Tales",
MediaType = ItemType.Book,
MediumInfo = new Medium { Id = 2, MediaType = ItemType.Book, Name = "Book" }
};
var bluRay = new MediaItem
{
Id = 3,
Name = "The Mummy",
MediaType = ItemType.Video,
MediumInfo = new Medium { Id = 3, MediaType = ItemType.Video, Name = "Blu Ray" }
};
items = new ObservableCollection<MediaItem>
{
cd,
book,
bluRay
};
allItems = new ObservableCollection<MediaItem>(Items);
mediums = new List<string>
{
"All",
nameof(ItemType.Book),
nameof(ItemType.Music),
nameof(ItemType.Video)
};
selectedMedium = Mediums[0];
}
public ObservableCollection<MediaItem> Items
{
get
{
return items;
}
set
{
SetProperty(ref items, value);
}
}
public IList<string> Mediums
{
get
{
return mediums;
}
set
{
SetProperty(ref mediums, value);
}
}
public string SelectedMedium
{
get
{
return selectedMedium;
}
set
{
SetProperty(ref selectedMedium, value);
Items.Clear();
foreach (var item in allItems)
{
if (string.IsNullOrWhiteSpace(selectedMedium) ||
selectedMedium == "All" ||
selectedMedium == item.MediaType.ToString())
{
Items.Add(item);
}
}
}
}
public MediaItem SelectedMediaItem
{
get => selectedMediaItem;
set
{
SetProperty(ref selectedMediaItem, value);
}
}
public void AddOrEditItem()
{
// Note this is temporary until
// we use a real data source for items.
const int startingItemCount = 3;
var newItem = new MediaItem
{
Id = startingItemCount + additionalItemCount,
Location = LocationType.InCollection,
MediaType = ItemType.Music,
MediumInfo = new Medium { Id = 1, MediaType = ItemType.Music, Name = "CD" },
Name = $"CD {additionalItemCount}"
};
Items.Add(newItem);
additionalItemCount++;
}
public void DeleteItem()
{
Items.Remove(SelectedMediaItem);
}
}
}
@@ -0,0 +1,165 @@
using MyMediaCollection.Enums;
using MyMediaCollection.Model;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows.Input;
namespace MyMediaCollection.ViewModels
{
public class MainViewModel : BindableBase
{
private string selectedMedium;
private ObservableCollection<MediaItem> items;
private ObservableCollection<MediaItem> allItems;
private IList<string> mediums;
private MediaItem selectedMediaItem;
private int additionalItemCount = 1;
public MainViewModel()
{
PopulateData();
DeleteCommand = new RelayCommand(DeleteItem, CanDeleteItem);
// No CanExecute param is needed for this command
// because you can always add or edit items.
AddEditCommand = new RelayCommand(AddOrEditItem);
}
public void PopulateData()
{
var cd = new MediaItem
{
Id = 1,
Name = "Classical Favorites",
MediaType = ItemType.Music,
MediumInfo = new Medium { Id = 1, MediaType = ItemType.Music, Name = "CD" }
};
var book = new MediaItem
{
Id = 2,
Name = "Classic Fairy Tales",
MediaType = ItemType.Book,
MediumInfo = new Medium { Id = 2, MediaType = ItemType.Book, Name = "Book" }
};
var bluRay = new MediaItem
{
Id = 3,
Name = "The Mummy",
MediaType = ItemType.Video,
MediumInfo = new Medium { Id = 3, MediaType = ItemType.Video, Name = "Blu Ray" }
};
items = new ObservableCollection<MediaItem>
{
cd,
book,
bluRay
};
allItems = new ObservableCollection<MediaItem>(Items);
mediums = new List<string>
{
"All",
nameof(ItemType.Book),
nameof(ItemType.Music),
nameof(ItemType.Video)
};
selectedMedium = Mediums[0];
}
public ObservableCollection<MediaItem> Items
{
get
{
return items;
}
set
{
SetProperty(ref items, value);
}
}
public IList<string> Mediums
{
get
{
return mediums;
}
set
{
SetProperty(ref mediums, value);
}
}
public string SelectedMedium
{
get
{
return selectedMedium;
}
set
{
SetProperty(ref selectedMedium, value);
Items.Clear();
foreach (var item in allItems)
{
if (string.IsNullOrWhiteSpace(selectedMedium) ||
selectedMedium == "All" ||
selectedMedium == item.MediaType.ToString())
{
Items.Add(item);
}
}
}
}
public MediaItem SelectedMediaItem
{
get => selectedMediaItem;
set
{
SetProperty(ref selectedMediaItem, value);
((RelayCommand)DeleteCommand).RaiseCanExecuteChanged();
}
}
public ICommand AddEditCommand { get; set; }
public void AddOrEditItem()
{
// Note this is temporary until
// we use a real data source for items.
const int startingItemCount = 3;
var newItem = new MediaItem
{
Id = startingItemCount + additionalItemCount,
Location = LocationType.InCollection,
MediaType = ItemType.Music,
MediumInfo = new Medium { Id = 1, MediaType = ItemType.Music, Name = "CD" },
Name = $"CD {additionalItemCount}"
};
allItems.Add(newItem);
Items.Add(newItem);
additionalItemCount++;
}
public ICommand DeleteCommand { get; set; }
public void DeleteItem()
{
allItems.Remove(SelectedMediaItem);
Items.Remove(SelectedMediaItem);
}
private bool CanDeleteItem() => selectedMediaItem != null;
}
}
@@ -0,0 +1,33 @@
using System;
using System.Windows.Input;
namespace MyMediaCollection.ViewModels
{
public class RelayCommand : ICommand
{
private readonly Action action;
private readonly Func<bool> canExecute;
public RelayCommand(Action action)
: this(action, null)
{
}
public RelayCommand(Action action, Func<bool> canExecute)
{
if (action == null)
throw new ArgumentNullException(nameof(action));
this.action = action;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter) => canExecute == null || canExecute();
public void Execute(object parameter) => action();
public event EventHandler CanExecuteChanged;
public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MyMediaCollection.app"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!--The ID below informs the system that this application is compatible with OS features first introduced in Windows 8.
For more info see https://docs.microsoft.com/windows/win32/sysinfo/targeting-your-application-at-windows-8-1
It is also necessary to support features in unpackaged applications, for example the custom titlebar implementation.-->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
</application>
</compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<!-- The combination of below two tags have the following effect:
1) Per-Monitor for >= Windows 10 Anniversary Update
2) System < Windows 10 Anniversary Update
-->
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
</windowsSettings>
</application>
</assembly>