更新客户端渲染,更新了壳

This commit is contained in:
QWQLwToo
2026-07-06 23:05:40 +08:00
parent e7dd87bf7e
commit 31d778710b
1311 changed files with 172662 additions and 1582 deletions
@@ -0,0 +1,18 @@
<Application
x:Class="Wpf.Ui.Demo.Mvvm.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
DispatcherUnhandledException="OnDispatcherUnhandledException"
Exit="OnExit"
Startup="OnStartup"
>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ui:ThemesDictionary Theme="Light" />
<ui:ControlsDictionary />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
@@ -0,0 +1,104 @@
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
using System.IO;
using System.Windows.Threading;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Wpf.Ui.Demo.Mvvm.Models;
using Wpf.Ui.Demo.Mvvm.Services;
using Wpf.Ui.DependencyInjection;
namespace Wpf.Ui.Demo.Mvvm;
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App
{
// The.NET Generic Host provides dependency injection, configuration, logging, and other services.
// https://docs.microsoft.com/dotnet/core/extensions/generic-host
// https://docs.microsoft.com/dotnet/core/extensions/dependency-injection
// https://docs.microsoft.com/dotnet/core/extensions/configuration
// https://docs.microsoft.com/dotnet/core/extensions/logging
private static readonly IHost _host = Host.CreateDefaultBuilder()
.ConfigureAppConfiguration(c =>
{
var basePath =
Path.GetDirectoryName(AppContext.BaseDirectory)
?? throw new DirectoryNotFoundException(
"Unable to find the base directory of the application."
);
_ = c.SetBasePath(basePath);
})
.ConfigureServices(
(context, services) =>
{
_ = services.AddNavigationViewPageProvider();
// App Host
_ = services.AddHostedService<ApplicationHostService>();
// Theme manipulation
_ = services.AddSingleton<IThemeService, ThemeService>();
// TaskBar manipulation
_ = services.AddSingleton<ITaskBarService, TaskBarService>();
// Service containing navigation, same as INavigationWindow... but without window
_ = services.AddSingleton<INavigationService, NavigationService>();
// Main window with navigation
_ = services.AddSingleton<INavigationWindow, Views.MainWindow>();
_ = services.AddSingleton<ViewModels.MainWindowViewModel>();
// Views and ViewModels
_ = services.AddSingleton<Views.Pages.DashboardPage>();
_ = services.AddSingleton<ViewModels.DashboardViewModel>();
_ = services.AddSingleton<Views.Pages.DataPage>();
_ = services.AddSingleton<ViewModels.DataViewModel>();
_ = services.AddSingleton<Views.Pages.SettingsPage>();
_ = services.AddSingleton<ViewModels.SettingsViewModel>();
// Configuration
_ = services.Configure<AppConfig>(context.Configuration.GetSection(nameof(AppConfig)));
}
)
.Build();
/// <summary>
/// Gets services.
/// </summary>
public static IServiceProvider Services
{
get { return _host.Services; }
}
/// <summary>
/// Occurs when the application is loading.
/// </summary>
private async void OnStartup(object sender, StartupEventArgs e)
{
await _host.StartAsync();
}
/// <summary>
/// Occurs when the application is closing.
/// </summary>
private async void OnExit(object sender, ExitEventArgs e)
{
await _host.StopAsync();
_host.Dispose();
}
/// <summary>
/// Occurs when an exception is thrown by an application but not handled.
/// </summary>
private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
// For more info see https://docs.microsoft.com/en-us/dotnet/api/system.windows.application.dispatcherunhandledexception?view=windowsdesktop-6.0
}
}
@@ -0,0 +1,6 @@
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

@@ -0,0 +1,15 @@
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
global using System;
global using System.Collections.Generic;
global using System.Globalization;
global using System.Linq;
global using System.Threading;
global using System.Threading.Tasks;
global using System.Windows;
global using CommunityToolkit.Mvvm.ComponentModel;
global using CommunityToolkit.Mvvm.Input;
global using Microsoft.Extensions.Hosting;
@@ -0,0 +1,38 @@
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
using System.Windows.Data;
namespace Wpf.Ui.Demo.Mvvm.Helpers;
internal class EnumToBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (parameter is not string enumString)
{
throw new ArgumentException("ExceptionEnumToBooleanConverterParameterMustBeAnEnumName");
}
if (!Enum.IsDefined(typeof(Wpf.Ui.Appearance.ApplicationTheme), value))
{
throw new ArgumentException("ExceptionEnumToBooleanConverterValueMustBeAnEnum");
}
var enumValue = Enum.Parse(typeof(Wpf.Ui.Appearance.ApplicationTheme), enumString);
return enumValue.Equals(value);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (parameter is not string enumString)
{
throw new ArgumentException("ExceptionEnumToBooleanConverterParameterMustBeAnEnumName");
}
return Enum.Parse(typeof(Wpf.Ui.Appearance.ApplicationTheme), enumString);
}
}
@@ -0,0 +1,13 @@
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
namespace Wpf.Ui.Demo.Mvvm.Models;
public class AppConfig
{
public string? ConfigurationsFolder { get; set; }
public string? AppPropertiesFileName { get; set; }
}
@@ -0,0 +1,13 @@
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
using System.Windows.Media;
namespace Wpf.Ui.Demo.Mvvm.Models;
public struct DataColor
{
public Brush Color { get; set; }
}
@@ -0,0 +1,52 @@
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
using Wpf.Ui.Demo.Mvvm.Views;
namespace Wpf.Ui.Demo.Mvvm.Services;
/// <summary>
/// Managed host of the application.
/// </summary>
public class ApplicationHostService(IServiceProvider serviceProvider) : IHostedService
{
private INavigationWindow? _navigationWindow;
/// <summary>
/// Triggered when the application host is ready to start the service.
/// </summary>
/// <param name="cancellationToken">Indicates that the start process has been aborted.</param>
public async Task StartAsync(CancellationToken cancellationToken)
{
await HandleActivationAsync();
}
/// <summary>
/// Triggered when the application host is performing a graceful shutdown.
/// </summary>
/// <param name="cancellationToken">Indicates that the shutdown process should no longer be graceful.</param>
public async Task StopAsync(CancellationToken cancellationToken)
{
await Task.CompletedTask;
}
/// <summary>
/// Creates main window during activation.
/// </summary>
private async Task HandleActivationAsync()
{
await Task.CompletedTask;
if (!Application.Current.Windows.OfType<MainWindow>().Any())
{
_navigationWindow = (serviceProvider.GetService(typeof(INavigationWindow)) as INavigationWindow)!;
_navigationWindow!.ShowWindow();
_ = _navigationWindow.Navigate(typeof(Views.Pages.DashboardPage));
}
await Task.CompletedTask;
}
}
@@ -0,0 +1,18 @@
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
namespace Wpf.Ui.Demo.Mvvm.ViewModels;
public partial class DashboardViewModel : ViewModel
{
[ObservableProperty]
private int _counter = 0;
[RelayCommand]
private void OnCounterIncrement()
{
Counter++;
}
}
@@ -0,0 +1,50 @@
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
using System.Windows.Media;
using Wpf.Ui.Demo.Mvvm.Models;
namespace Wpf.Ui.Demo.Mvvm.ViewModels;
public partial class DataViewModel : ViewModel
{
private bool _isInitialized = false;
[ObservableProperty]
private List<DataColor> _colors = [];
public override void OnNavigatedTo()
{
if (!_isInitialized)
{
InitializeViewModel();
}
}
private void InitializeViewModel()
{
var random = new Random();
Colors.Clear();
for (int i = 0; i < 8192; i++)
{
Colors.Add(
new DataColor
{
Color = new SolidColorBrush(
Color.FromArgb(
(byte)200,
(byte)random.Next(0, 250),
(byte)random.Next(0, 250),
(byte)random.Next(0, 250)
)
),
}
);
}
_isInitialized = true;
}
}
@@ -0,0 +1,74 @@
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
using System.Collections.ObjectModel;
using Wpf.Ui.Controls;
namespace Wpf.Ui.Demo.Mvvm.ViewModels;
public partial class MainWindowViewModel : ViewModel
{
private bool _isInitialized = false;
[ObservableProperty]
private string _applicationTitle = string.Empty;
[ObservableProperty]
private ObservableCollection<object> _navigationItems = [];
[ObservableProperty]
private ObservableCollection<object> _navigationFooter = [];
[ObservableProperty]
private ObservableCollection<MenuItem> _trayMenuItems = [];
[System.Diagnostics.CodeAnalysis.SuppressMessage(
"Style",
"IDE0060:Remove unused parameter",
Justification = "Demo"
)]
public MainWindowViewModel(INavigationService navigationService)
{
if (!_isInitialized)
{
InitializeViewModel();
}
}
private void InitializeViewModel()
{
ApplicationTitle = "WPF UI - MVVM Demo";
NavigationItems =
[
new NavigationViewItem()
{
Content = "Home",
Icon = new SymbolIcon { Symbol = SymbolRegular.Home24 },
TargetPageType = typeof(Views.Pages.DashboardPage),
},
new NavigationViewItem()
{
Content = "Data",
Icon = new SymbolIcon { Symbol = SymbolRegular.DataHistogram24 },
TargetPageType = typeof(Views.Pages.DataPage),
},
];
NavigationFooter =
[
new NavigationViewItem()
{
Content = "Settings",
Icon = new SymbolIcon { Symbol = SymbolRegular.Settings24 },
TargetPageType = typeof(Views.Pages.SettingsPage),
},
];
TrayMenuItems = [new() { Header = "Home", Tag = "tray_home" }];
_isInitialized = true;
}
}
@@ -0,0 +1,71 @@
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
namespace Wpf.Ui.Demo.Mvvm.ViewModels;
public partial class SettingsViewModel : ViewModel
{
private bool _isInitialized = false;
[ObservableProperty]
private string _appVersion = string.Empty;
[ObservableProperty]
private Wpf.Ui.Appearance.ApplicationTheme _currentApplicationTheme = Wpf.Ui
.Appearance
.ApplicationTheme
.Unknown;
public override void OnNavigatedTo()
{
if (!_isInitialized)
{
InitializeViewModel();
}
}
private void InitializeViewModel()
{
CurrentApplicationTheme = Wpf.Ui.Appearance.ApplicationThemeManager.GetAppTheme();
AppVersion = $"Wpf.Ui.Demo.Mvvm - {GetAssemblyVersion()}";
_isInitialized = true;
}
private static string GetAssemblyVersion()
{
return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version?.ToString()
?? string.Empty;
}
[RelayCommand]
private void OnChangeTheme(string parameter)
{
switch (parameter)
{
case "theme_light":
if (CurrentApplicationTheme == Wpf.Ui.Appearance.ApplicationTheme.Light)
{
break;
}
Wpf.Ui.Appearance.ApplicationThemeManager.Apply(Wpf.Ui.Appearance.ApplicationTheme.Light);
CurrentApplicationTheme = Wpf.Ui.Appearance.ApplicationTheme.Light;
break;
default:
if (CurrentApplicationTheme == Wpf.Ui.Appearance.ApplicationTheme.Dark)
{
break;
}
Wpf.Ui.Appearance.ApplicationThemeManager.Apply(Wpf.Ui.Appearance.ApplicationTheme.Dark);
CurrentApplicationTheme = Wpf.Ui.Appearance.ApplicationTheme.Dark;
break;
}
}
}
@@ -0,0 +1,39 @@
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
using Wpf.Ui.Abstractions.Controls;
namespace Wpf.Ui.Demo.Mvvm.ViewModels;
public abstract class ViewModel : ObservableObject, INavigationAware
{
/// <inheritdoc />
public virtual Task OnNavigatedToAsync()
{
OnNavigatedTo();
return Task.CompletedTask;
}
/// <summary>
/// Handles the event that is fired after the component is navigated to.
/// </summary>
// ReSharper disable once MemberCanBeProtected.Global
public virtual void OnNavigatedTo() { }
/// <inheritdoc />
public virtual Task OnNavigatedFromAsync()
{
OnNavigatedFrom();
return Task.CompletedTask;
}
/// <summary>
/// Handles the event that is fired before the component is navigated from.
/// </summary>
// ReSharper disable once MemberCanBeProtected.Global
public virtual void OnNavigatedFrom() { }
}
@@ -0,0 +1,74 @@
<ui:FluentWindow
x:Class="Wpf.Ui.Demo.Mvvm.Views.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:local="clr-namespace:Wpf.Ui.Demo.Mvvm.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tray="http://schemas.lepo.co/wpfui/2022/xaml/tray"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
Title="{Binding ViewModel.ApplicationTitle, Mode=OneWay}"
Width="1100"
Height="650"
d:DataContext="{d:DesignInstance local:MainWindow,
IsDesignTimeCreatable=True}"
d:DesignHeight="450"
d:DesignWidth="800"
ui:Design.Background="{DynamicResource ApplicationBackgroundBrush}"
ui:Design.Foreground="{DynamicResource TextFillColorPrimaryBrush}"
ExtendsContentIntoTitleBar="True"
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
WindowBackdropType="Mica"
WindowCornerPreference="Round"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d"
>
<ui:FluentWindow.InputBindings>
<KeyBinding
Key="F"
Command="{Binding ElementName=AutoSuggestBox, Path=FocusCommand}"
Modifiers="Control"
/>
</ui:FluentWindow.InputBindings>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ui:NavigationView
x:Name="RootNavigation"
Grid.Row="1"
FooterMenuItemsSource="{Binding ViewModel.NavigationFooter, Mode=OneWay}"
MenuItemsSource="{Binding ViewModel.NavigationItems, Mode=OneWay}"
>
<ui:NavigationView.AutoSuggestBox>
<ui:AutoSuggestBox x:Name="AutoSuggestBox" PlaceholderText="Search">
<ui:AutoSuggestBox.Icon>
<ui:IconSourceElement>
<ui:SymbolIconSource Symbol="Search24" />
</ui:IconSourceElement>
</ui:AutoSuggestBox.Icon>
</ui:AutoSuggestBox>
</ui:NavigationView.AutoSuggestBox>
<ui:NavigationView.Header>
<ui:BreadcrumbBar Margin="42,32,0,0" FontSize="28" FontWeight="DemiBold" />
</ui:NavigationView.Header>
</ui:NavigationView>
<ui:TitleBar
Title="{Binding ViewModel.ApplicationTitle, Mode=OneWay}"
Grid.Row="0"
Icon="pack://application:,,,/Assets/applicationIcon-256.png"
/>
<tray:NotifyIcon
Grid.Row="0"
FocusOnLeftClick="True"
Icon="pack://application:,,,/Assets/applicationIcon-256.png"
MenuOnRightClick="True"
TooltipText="WPF UI - MVVM Demo"
>
<tray:NotifyIcon.Menu>
<ContextMenu ItemsSource="{Binding ViewModel.TrayMenuItems, Mode=OneWay}" />
</tray:NotifyIcon.Menu>
</tray:NotifyIcon>
</Grid>
</ui:FluentWindow>
@@ -0,0 +1,61 @@
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
using Wpf.Ui.Abstractions;
using Wpf.Ui.Controls;
namespace Wpf.Ui.Demo.Mvvm.Views;
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : INavigationWindow
{
public ViewModels.MainWindowViewModel ViewModel { get; }
public MainWindow(ViewModels.MainWindowViewModel viewModel, INavigationService navigationService)
{
ViewModel = viewModel;
DataContext = this;
Appearance.SystemThemeWatcher.Watch(this);
InitializeComponent();
navigationService.SetNavigationControl(RootNavigation);
}
public INavigationView GetNavigation() => RootNavigation;
public bool Navigate(Type pageType) => RootNavigation.Navigate(pageType);
public void SetPageService(INavigationViewPageProvider navigationViewPageProvider) =>
RootNavigation.SetPageProviderService(navigationViewPageProvider);
public void ShowWindow() => Show();
public void CloseWindow() => Close();
/// <summary>
/// Raises the closed event.
/// </summary>
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
// Make sure that closing this window will begin the process of closing the application.
Application.Current.Shutdown();
}
INavigationView INavigationWindow.GetNavigation()
{
throw new NotImplementedException();
}
public void SetServiceProvider(IServiceProvider serviceProvider)
{
throw new NotImplementedException();
}
}
@@ -0,0 +1,37 @@
<Page
x:Class="Wpf.Ui.Demo.Mvvm.Views.Pages.DashboardPage"
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:local="clr-namespace:Wpf.Ui.Demo.Mvvm.Views.Pages"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
Title="DashboardPage"
d:DataContext="{d:DesignInstance local:DashboardPage,
IsDesignTimeCreatable=False}"
d:DesignHeight="450"
d:DesignWidth="800"
ui:Design.Background="{DynamicResource ApplicationBackgroundBrush}"
ui:Design.Foreground="{DynamicResource TextFillColorPrimaryBrush}"
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
mc:Ignorable="d"
>
<Grid Margin="42" VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ui:Button
Grid.Column="0"
Command="{Binding ViewModel.CounterIncrementCommand, Mode=OneWay}"
Content="Click me!"
Icon="{ui:SymbolIcon Fluent24}"
/>
<TextBlock
Grid.Column="1"
Margin="12,0,0,0"
VerticalAlignment="Center"
Text="{Binding ViewModel.Counter, Mode=OneWay}"
/>
</Grid>
</Page>
@@ -0,0 +1,24 @@
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
using Wpf.Ui.Abstractions.Controls;
namespace Wpf.Ui.Demo.Mvvm.Views.Pages;
/// <summary>
/// Interaction logic for DashboardPage.xaml
/// </summary>
public partial class DashboardPage : INavigableView<ViewModels.DashboardViewModel>
{
public ViewModels.DashboardViewModel ViewModel { get; }
public DashboardPage(ViewModels.DashboardViewModel viewModel)
{
ViewModel = viewModel;
DataContext = this;
InitializeComponent();
}
}
@@ -0,0 +1,45 @@
<Page
x:Class="Wpf.Ui.Demo.Mvvm.Views.Pages.DataPage"
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:local="clr-namespace:Wpf.Ui.Demo.Mvvm.Views.Pages"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:models="clr-namespace:Wpf.Ui.Demo.Mvvm.Models"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
Title="DataPage"
d:DataContext="{d:DesignInstance local:DataPage,
IsDesignTimeCreatable=False}"
d:DesignHeight="450"
d:DesignWidth="800"
ui:Design.Background="{DynamicResource ApplicationBackgroundBrush}"
ui:Design.Foreground="{DynamicResource TextFillColorPrimaryBrush}"
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
ScrollViewer.CanContentScroll="False"
mc:Ignorable="d"
>
<Grid Margin="42">
<ui:VirtualizingItemsControl
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
ItemsSource="{Binding ViewModel.Colors, Mode=OneWay}"
VirtualizingPanel.CacheLengthUnit="Item"
>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type models:DataColor}">
<ui:Button
Width="80"
Height="80"
Margin="2"
Padding="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Appearance="Secondary"
Background="{Binding Color, Mode=OneWay}"
FontSize="25"
Icon="Fluent24"
/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ui:VirtualizingItemsControl>
</Grid>
</Page>
@@ -0,0 +1,24 @@
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
using Wpf.Ui.Abstractions.Controls;
namespace Wpf.Ui.Demo.Mvvm.Views.Pages;
/// <summary>
/// Interaction logic for DataView.xaml
/// </summary>
public partial class DataPage : INavigableView<ViewModels.DataViewModel>
{
public ViewModels.DataViewModel ViewModel { get; }
public DataPage(ViewModels.DataViewModel viewModel)
{
ViewModel = viewModel;
DataContext = this;
InitializeComponent();
}
}
@@ -0,0 +1,45 @@
<Page
x:Class="Wpf.Ui.Demo.Mvvm.Views.Pages.SettingsPage"
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:helpers="clr-namespace:Wpf.Ui.Demo.Mvvm.Helpers"
xmlns:local="clr-namespace:Wpf.Ui.Demo.Mvvm.Views.Pages"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
Title="SettingsPage"
d:DataContext="{d:DesignInstance local:SettingsPage,
IsDesignTimeCreatable=False}"
d:DesignHeight="450"
d:DesignWidth="800"
ui:Design.Background="{DynamicResource ApplicationBackgroundBrush}"
ui:Design.Foreground="{DynamicResource TextFillColorPrimaryBrush}"
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
mc:Ignorable="d"
>
<Page.Resources>
<helpers:EnumToBooleanConverter x:Key="EnumToBooleanConverter" />
</Page.Resources>
<StackPanel Margin="42">
<TextBlock FontSize="20" FontWeight="Medium" Text="Personalization" />
<TextBlock Margin="0,12,0,0" Text="Theme" />
<RadioButton
Margin="0,12,0,0"
Command="{Binding ViewModel.ChangeThemeCommand, Mode=OneWay}"
CommandParameter="theme_light"
Content="Light"
GroupName="themeSelect"
IsChecked="{Binding ViewModel.CurrentApplicationTheme, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter=Light, Mode=OneWay}"
/>
<RadioButton
Margin="0,8,0,0"
Command="{Binding ViewModel.ChangeThemeCommand, Mode=OneWay}"
CommandParameter="theme_dark"
Content="Dark"
GroupName="themeSelect"
IsChecked="{Binding ViewModel.CurrentApplicationTheme, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter=Dark, Mode=OneWay}"
/>
<TextBlock Margin="0,24,0,0" FontSize="20" FontWeight="Medium" Text="About Wpf.Ui.Demo.Mvvm" />
<TextBlock Margin="0,12,0,0" Text="{Binding ViewModel.AppVersion, Mode=OneWay}" />
</StackPanel>
</Page>
@@ -0,0 +1,24 @@
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
using Wpf.Ui.Abstractions.Controls;
namespace Wpf.Ui.Demo.Mvvm.Views.Pages;
/// <summary>
/// Interaction logic for SettingsPage.xaml
/// </summary>
public partial class SettingsPage : INavigableView<ViewModels.SettingsViewModel>
{
public ViewModels.SettingsViewModel ViewModel { get; }
public SettingsPage(ViewModels.SettingsViewModel viewModel)
{
ViewModel = viewModel;
DataContext = this;
InitializeComponent();
}
}
@@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net10.0-windows10.0.26100.0</TargetFramework>
<SupportedOSPlatformVersion>10.0.17763.0</SupportedOSPlatformVersion>
<UseWPF>true</UseWPF>
<ApplicationManifest>app.manifest</ApplicationManifest>
<ApplicationIcon>applicationIcon.ico</ApplicationIcon>
<NoWarn>$(NoWarn);SA1601</NoWarn>
</PropertyGroup>
<ItemGroup>
<Content Include="applicationIcon.ico" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" />
<PackageReference Include="CommunityToolkit.Mvvm" />
</ItemGroup>
<ItemGroup>
<None Remove="Assets\applicationIcon-1024.png" />
<None Remove="Assets\applicationIcon-256.png" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Wpf.Ui.DependencyInjection\Wpf.Ui.DependencyInjection.csproj" />
<ProjectReference Include="..\..\src\Wpf.Ui.ToastNotifications\Wpf.Ui.ToastNotifications.csproj" />
<ProjectReference Include="..\..\src\Wpf.Ui.Tray\Wpf.Ui.Tray.csproj" />
<ProjectReference Include="..\..\src\Wpf.Ui\Wpf.Ui.csproj" />
</ItemGroup>
<ItemGroup>
<Resource Include="Assets\applicationIcon-1024.png" />
<Resource Include="Assets\applicationIcon-256.png" />
</ItemGroup>
</Project>
@@ -0,0 +1,75 @@
<?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="Wpf.Ui.Demo.Mvvm.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC Manifest Options
If you want to change the Windows User Account Control level replace the
requestedExecutionLevel node with one of the following.
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
Specifying requestedExecutionLevel element will disable file and registry virtualization.
Remove this element if your application requires this virtualization for backwards
compatibility.
-->
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on
and is designed to work with. Uncomment the appropriate elements
and Windows will automatically select the most compatible environment. -->
<!-- Windows Vista -->
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
<!-- Windows 7 -->
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
<!-- Windows 8 -->
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
<!-- Windows 8.1 -->
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
<!-- Indicates that the application is DPI-aware and will not be automatically scaled by Windows at higher
DPIs. Windows Presentation Foundation (WPF) applications are automatically DPI-aware and do not need
to opt in. Windows Forms applications targeting .NET Framework 4.6 that opt into this setting, should
also set the 'EnableWindowsFormsHighDpiAutoResizing' setting to 'true' in their app.config.
Makes the application long-path aware. See https://docs.microsoft.com/windows/win32/fileio/maximum-file-path-limitation -->
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitor</dpiAwareness>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings>
</application>
<!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*" />
</dependentAssembly>
</dependency>
</assembly>
Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB