WPF中Prism框架的应用
仓库地址:Link
1 下载Style,Prism包
1.1 TestUIForPrism.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<None Remove="Resources\Eric.ico" />
<None Remove="Resources\EricssonBuiding.jpg" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MaterialDesignThemes" Version="4.9.0" />
<PackageReference Include="Prism.Unity" Version="8.1.97" />
<PackageReference Include="WindowsAPICodePack-Shell" Version="1.1.1" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Eric.ico" />
</ItemGroup>
</Project>
1.2 App.xaml
<prism:PrismApplication x:Class="TestUIForPrism.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestUIForPrism"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:prism="http://prismlibrary.com/" >
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<materialDesign:BundledTheme BaseTheme="Dark" PrimaryColor="LightBlue" SecondaryColor="DeepOrange" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</prism:PrismApplication>
code behind:
using Prism.Ioc;
using System.Windows;
using TestUIForPrism.Views;
namespace TestUIForPrism
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App
{
protected override Window CreateShell()
{
return Container.Resolve<MainWindow>();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<Analyzer>();
containerRegistry.RegisterForNavigation<Maker>();
}
}
}
2 Views
2.1 MainWindow.xaml
<Window x:Class="TestUIForPrism.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
Background="{DynamicResource MaterialDesignPaper}"
TextElement.FontWeight="Medium"
TextElement.FontSize="14"
FontFamily="{materialDesign:MaterialDesignFont}"
Icon="../Resources/Eric.ico"
Title="{Binding Title}" Height="700" Width="700" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="2*"/>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="0" Grid.ColumnSpan="3" Margin="30" Orientation="Horizontal">
<Button Content="Maker" Command="{Binding MakerCommand}" />
<Button Content="Analyzer" Command="{Binding AnalyzerCommand}" />
<Button Content="Default" Command="{Binding DefaultCommand}" />
<Button Content="Default" Command="{Binding DefaultCommand}" />
</StackPanel>
<ContentControl Grid.Row="1" Grid.ColumnSpan="3" Grid.RowSpan="2" Margin="20" prism:RegionManager.RegionName="ContentRegion" />
</Grid>
</Window>
code behind: 主要是自定义增加文本框随着Log输出自从下拉功能
using System.Collections.Generic;
using System;
using System.Windows;
using System.Windows.Controls;
namespace TestUIForPrism.Views
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
/// <summary>
/// Attach a Property for Autoscrolling TextBox
/// </summary>
public class TextBoxBehaviour
{
static readonly Dictionary<TextBox, Capture> _associations = new Dictionary<TextBox, Capture>();
public static bool GetScrollOnTextChanged(DependencyObject dependencyObject)
{
return (bool)dependencyObject.GetValue(ScrollOnTextChangedProperty);
}
public static void SetScrollOnTextChanged(DependencyObject dependencyObject, bool value)
{
dependencyObject.SetValue(ScrollOnTextChangedProperty, value);
}
public static readonly DependencyProperty ScrollOnTextChangedProperty =
DependencyProperty.RegisterAttached("ScrollOnTextChanged", typeof(bool), typeof(TextBoxBehaviour), new UIPropertyMetadata(false, OnScrollOnTextChanged));
static void OnScrollOnTextChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
var textBox = dependencyObject as TextBox;
if (textBox == null)
{
return;
}
bool oldValue = (bool)e.OldValue, newValue = (bool)e.NewValue;
if (newValue == oldValue)
{
return;
}
if (newValue)
{
textBox.Loaded += TextBoxLoaded;
textBox.Unloaded += TextBoxUnloaded;
}
else
{
textBox.Loaded -= TextBoxLoaded;
textBox.Unloaded -= TextBoxUnloaded;
if (_associations.ContainsKey(textBox))
{
_associations[textBox].Dispose();
}
}
}
static void TextBoxUnloaded(object sender, RoutedEventArgs routedEventArgs)
{
var textBox = (TextBox)sender;
_associations[textBox].Dispose();
textBox.Unloaded -= TextBoxUnloaded;
}
static void TextBoxLoaded(object sender, RoutedEventArgs routedEventArgs)
{
var textBox = (TextBox)sender;
textBox.Loaded -= TextBoxLoaded;
_associations[textBox] = new Capture(textBox);
}
class Capture : IDisposable
{
private TextBox TextBox { get; set; }
public Capture(TextBox textBox)
{
TextBox = textBox;
TextBox.TextChanged += OnTextBoxOnTextChanged;
}
private void OnTextBoxOnTextChanged(object sender, TextChangedEventArgs args)
{
TextBox.ScrollToEnd();
}
public void Dispose()
{
TextBox.TextChanged -= OnTextBoxOnTextChanged;
}
}
}
}
2.2 Maker.xaml
<UserControl x:Class="TestUIForPrism.Views.Maker"
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:TestUIForPrism.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="400">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition Height="2*"/>
<RowDefinition Height="2*"/>
<RowDefinition Height="2*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="12*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Margin="10" Text="Before.csv Directory" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBox Grid.Row="0" Grid.Column="1" Margin="10" Text="{Binding PathConfig, Mode=TwoWay}"/>
<Button Grid.Row="0" Grid.Column="2" Content="Reference" Margin="10" Command="{Binding CommandReference}">
<Button.CommandParameter>config</Button.CommandParameter>
</Button>
<TextBlock Grid.Row="1" Grid.Column="0" Margin="10" Text="Input Directory" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBox Grid.Row="1" Grid.Column="1" Margin="10" Text="{Binding PathInput, Mode=TwoWay}"/>
<Button Grid.Row="1" Grid.Column="2" Content="Reference" Margin="10" Command="{Binding CommandReference}">
<Button.CommandParameter>input</Button.CommandParameter>
</Button>
<TextBlock Grid.Row="2" Grid.Column="0" Margin="10" Text="Output Directory" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBox Grid.Row="2" Grid.Column="1" Margin="10" Text="{Binding PathOutput, Mode=TwoWay}"/>
<Button Grid.Row="2" Grid.Column="2" Content="Reference" Margin="10" Command="{Binding CommandReference}">
<Button.CommandParameter>output</Button.CommandParameter>
</Button>
<Button Grid.Row="3" Grid.Column="0" Content="Start" Margin="10" Command="{Binding CommandStart}"/>
<TextBlock Grid.Row="4" Margin="1" Text="Log" />
<TextBox Grid.Row="5" Grid.ColumnSpan="3" Text="{Binding Log}" local:TextBoxBehaviour.ScrollOnTextChanged="True" VerticalScrollBarVisibility="Auto"/>
</Grid>
</UserControl>
2.3 Analyzer.xaml
<UserControl x:Class="TestUIForPrism.Views.Analyzer"
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:TestUIForPrism.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="400">
<Grid Background="AliceBlue">
</Grid>
</UserControl>
3 ViewModels
2.1 MainWindowViewModel.cs
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using TestUIForPrism.Views;
namespace TestUIForPrism.ViewModels
{
public class MainWindowViewModel : BindableBase
{
private string _title = "Please Name Tool";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
/// <summary>
/// Region Navigation Controller in Prism Framework
/// </summary>
private readonly IRegionManager _regionManager;
public DelegateCommand AnalyzerCommand { get; private set; }
public DelegateCommand MakerCommand { get; private set; }
public MainWindowViewModel(IRegionManager regionManager)
{
this._regionManager = regionManager;
AnalyzerCommand = new DelegateCommand(Analyzer);
MakerCommand = new DelegateCommand(Maker);
}
void Analyzer()
{
if (_regionManager != null)
{
_regionManager.RequestNavigate("ContentRegion", "Analyzer");
}
}
void Maker()
{
if (_regionManager != null)
{
_regionManager.RequestNavigate("ContentRegion", "Maker");
}
}
}
}
2.2 MakerViewModel.cs
using Microsoft.WindowsAPICodePack.Dialogs;
using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Printing.IndexedProperties;
using System.Text;
using System.Threading.Tasks;
namespace TestUIForPrism.ViewModels
{
public class MakerViewModel : BindableBase
{
/// <summary>
/// For showing log in TextBox
/// </summary>
private string log = @"";
public string Log
{
get { return log; }
set
{
this.SetProperty(ref this.log, value + Environment.NewLine);
}
}
/// <summary>
/// For showing path in TextBoxs
/// </summary>
private string pathconfig;
public string PathConfig
{
get { return pathconfig; }
set { SetProperty(ref pathconfig, value); }
}
private string pathinput;
public string PathInput
{
get { return pathinput; }
set
{
SetProperty(ref pathinput, value);
CommandStart.RaiseCanExecuteChanged();
}
}
private string pathoutput;
public string PathOutput
{
get { return pathoutput; }
set
{
SetProperty(ref pathoutput, value);
CommandStart.RaiseCanExecuteChanged();
}
}
/// <summary>
/// For Start Button
/// </summary>
private DelegateCommand _fieldStart;
public DelegateCommand CommandStart =>
_fieldStart ?? (_fieldStart = new DelegateCommand(ExecuteCommandStart, CanExecuteCommandStart));
void ExecuteCommandStart()
{
// Test
string TextExample = "Test log function ~";
for (int i = 0; i < 100; i++)
{
this.Log += TextExample + " ==> " + i;
}
}
bool CanExecuteCommandStart()
{
if (string.IsNullOrEmpty(this.PathInput) || string.IsNullOrEmpty(this.PathOutput)) return false;
return true;
}
/// <summary>
/// For Reference Button
/// </summary>
private DelegateCommand<Object> _fieldReference;
public DelegateCommand<Object> CommandReference =>
_fieldReference ?? (_fieldReference = new DelegateCommand<Object>(ExecuteCommandReference, CanExecuteCommandReference));
void ExecuteCommandReference(Object parameter)
{
string type = (string)parameter;
if (type == "config")
{
this.PathConfig = @"..\..\TestUIForPrism\Config\Analizer.conf";
System.Windows.MessageBox.Show($"{this.PathConfig} will been set automatically");
}
else
{
//Please install WindowsAPICodePack-Shell in Nuget
using (var cofd = new CommonOpenFileDialog()
{
Title = "Please Select File",
InitialDirectory = @"",
IsFolderPicker = true,
})
{
if (cofd.ShowDialog() != CommonFileDialogResult.Ok)
{
return;
}
if (type == "input") this.PathInput = cofd.FileName;
else this.PathOutput = cofd.FileName;
System.Windows.MessageBox.Show($"{cofd.FileName} is Selected");
}
}
}
bool CanExecuteCommandReference(Object parameter)
{
return true;
}
}
}