Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
09768ad928 | ||
|
|
ef2a6522d1 |
60
CLAUDE.md
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
이 파일은 Claude Code (claude.ai/code)가 이 저장소에서 코드 작업을 할 때 참고하는 가이드입니다.
|
||||||
|
|
||||||
|
## 프로젝트 개요
|
||||||
|
|
||||||
|
EduToy는 WPF(Windows Presentation Foundation) 기초를 학습하기 위한 교육용 프로젝트입니다. "WPF 기초를 위한 토이프로젝트"라는 이름으로도 불립니다.
|
||||||
|
|
||||||
|
## 빌드 및 실행
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 프로젝트 빌드
|
||||||
|
cd src/WPFBeginner
|
||||||
|
dotnet build
|
||||||
|
|
||||||
|
# 프로젝트 실행
|
||||||
|
dotnet run
|
||||||
|
```
|
||||||
|
|
||||||
|
## 기술 스택
|
||||||
|
|
||||||
|
- **.NET 8.0** - Windows WPF 애플리케이션
|
||||||
|
- **CommunityToolkit.Mvvm 8.2.2** - MVVM 패턴 구현
|
||||||
|
- **Microsoft.Extensions.DependencyInjection 8.0.0** - 의존성 주입
|
||||||
|
|
||||||
|
## 프로젝트 아키텍처
|
||||||
|
|
||||||
|
```
|
||||||
|
src/WPFBeginner/
|
||||||
|
├── Models/ # 데이터 모델 (Member, AppSettings)
|
||||||
|
├── ViewModels/ # MVVM ViewModel (LoginViewModel, MainViewModel, RegistViewModel)
|
||||||
|
├── Views/ # XAML Window (LoginWindow, MainWindow, RegistWindow)
|
||||||
|
├── Controls/ # 재사용 가능한 UserControl (InputPanel)
|
||||||
|
├── Services/ # 비즈니스 로직 서비스 (SettingsService, MemberService)
|
||||||
|
├── Converters/ # WPF 값 변환기
|
||||||
|
└── Resources/
|
||||||
|
├── Themes/ # 테마 ResourceDictionary (DefaultTheme, LightTheme)
|
||||||
|
└── Languages/ # 다국어 리소스 (ko-KR, en-US)
|
||||||
|
```
|
||||||
|
|
||||||
|
## MVVM 패턴
|
||||||
|
|
||||||
|
- **View**: XAML만 사용, 코드 비하인드에 비즈니스 로직 없음
|
||||||
|
- **ViewModel**: CommunityToolkit.Mvvm의 `[ObservableProperty]`, `[RelayCommand]` 사용
|
||||||
|
- **DI**: App.xaml.cs에서 ServiceCollection으로 서비스 및 ViewModel 등록
|
||||||
|
|
||||||
|
## 주요 기능
|
||||||
|
|
||||||
|
- **로그인**: appsettings.json의 자격 증명으로 인증 (기본: admin/0000)
|
||||||
|
- **회원 관리**: DataGrid로 CRUD 작업
|
||||||
|
- **테마 전환**: 어두운 테마(Default) / 밝은 테마(Light)
|
||||||
|
- **다국어 지원**: 한국어(ko-KR) / 영어(en-US) 동적 전환
|
||||||
|
|
||||||
|
## 설정 파일
|
||||||
|
|
||||||
|
`appsettings.json`: 로그인 정보, 언어, 테마, 기본 회원 데이터 저장
|
||||||
|
|
||||||
|
## 언어
|
||||||
|
|
||||||
|
프로젝트 문서 및 UI는 한국어를 기본으로 사용합니다.
|
||||||
29
EduToy.sln
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.5.2.0
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{827E0CD3-B72D-47B6-A68D-7590B98EB39B}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WPFBeginner", "src\WPFBeginner\WPFBeginner.csproj", "{20E73DF0-D43D-8913-E28F-6960CD8A512D}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{20E73DF0-D43D-8913-E28F-6960CD8A512D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{20E73DF0-D43D-8913-E28F-6960CD8A512D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{20E73DF0-D43D-8913-E28F-6960CD8A512D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{20E73DF0-D43D-8913-E28F-6960CD8A512D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(NestedProjects) = preSolution
|
||||||
|
{20E73DF0-D43D-8913-E28F-6960CD8A512D} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {9791FF85-3B94-4645-B4A9-22D1B17C40A2}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
203
History.md
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
# 프로젝트 개발 히스토리
|
||||||
|
|
||||||
|
이 문서는 EduToy WPF 프로젝트의 개발 과정을 기록합니다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 프로젝트 분석 및 CLAUDE.md 생성
|
||||||
|
|
||||||
|
### 요청
|
||||||
|
- 코드베이스 분석 및 CLAUDE.md 파일 생성
|
||||||
|
|
||||||
|
### 작업 내용
|
||||||
|
- 프로젝트 구조 탐색
|
||||||
|
- "EduToy" - WPF 교육용 프로젝트로 확인
|
||||||
|
- docs/sampleApp/WPFBeginner.exe (컴파일된 바이너리) 발견
|
||||||
|
- CLAUDE.md 파일 영문으로 최초 작성
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 한국어 전환 및 CLAUDE.md 번역
|
||||||
|
|
||||||
|
### 요청
|
||||||
|
- 모든 대화를 한글로 진행
|
||||||
|
- CLAUDE.md를 한글로 번역
|
||||||
|
|
||||||
|
### 작업 내용
|
||||||
|
- CLAUDE.md 한국어로 번역 완료
|
||||||
|
- 프로젝트 문서화 한국어 기준으로 변경
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. WPF 애플리케이션 구현
|
||||||
|
|
||||||
|
### 요청
|
||||||
|
- PowerPoint 파일 (WPF 기초를 위한 토이프로젝트.pptx) 분석
|
||||||
|
- sampleApp 참고하여 프로그램 구현
|
||||||
|
|
||||||
|
### 기술 스택
|
||||||
|
- **.NET 8.0** Windows WPF
|
||||||
|
- **CommunityToolkit.Mvvm 8.2.2** - MVVM 패턴
|
||||||
|
- **Microsoft.Extensions.DependencyInjection 8.0.0** - DI
|
||||||
|
|
||||||
|
### 구현된 구조
|
||||||
|
```
|
||||||
|
src/WPFBeginner/
|
||||||
|
├── Models/
|
||||||
|
│ ├── Member.cs
|
||||||
|
│ └── AppSettings.cs
|
||||||
|
├── ViewModels/
|
||||||
|
│ ├── LoginViewModel.cs
|
||||||
|
│ ├── MainViewModel.cs
|
||||||
|
│ └── RegistViewModel.cs
|
||||||
|
├── Views/
|
||||||
|
│ ├── LoginWindow.xaml / .cs
|
||||||
|
│ ├── MainWindow.xaml / .cs
|
||||||
|
│ └── RegistWindow.xaml / .cs
|
||||||
|
├── Controls/
|
||||||
|
│ └── InputPanel.xaml / .cs
|
||||||
|
├── Services/
|
||||||
|
│ ├── SettingsService.cs
|
||||||
|
│ └── MemberService.cs
|
||||||
|
├── Converters/
|
||||||
|
│ └── BoolToVisibilityConverter.cs
|
||||||
|
└── Resources/
|
||||||
|
├── Themes/
|
||||||
|
│ ├── DefaultTheme.xaml
|
||||||
|
│ └── LightTheme.xaml
|
||||||
|
└── Languages/
|
||||||
|
├── ko-KR.xaml
|
||||||
|
└── en-US.xaml
|
||||||
|
```
|
||||||
|
|
||||||
|
### 주요 기능
|
||||||
|
- 로그인 (appsettings.json 자격 증명)
|
||||||
|
- 회원 관리 (DataGrid CRUD)
|
||||||
|
- 테마 전환 (Dark/Light)
|
||||||
|
- 다국어 지원 (한국어/영어)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 검색 영역 짤림 현상 수정
|
||||||
|
|
||||||
|
### 요청
|
||||||
|
- 창 크기 줄였을 때 검색 영역이 짤리는 현상 수정
|
||||||
|
- 엔터키로 검색 가능하도록 기능 개선
|
||||||
|
|
||||||
|
### 해결 방법
|
||||||
|
- MinWidth="700" MinHeight="400" 설정
|
||||||
|
- SearchTextBox_KeyDown 이벤트 핸들러 추가
|
||||||
|
|
||||||
|
### 수정 파일
|
||||||
|
- `MainWindow.xaml` - MinWidth/MinHeight 추가
|
||||||
|
- `MainWindow.xaml.cs` - KeyDown 이벤트 처리
|
||||||
|
```csharp
|
||||||
|
private void SearchTextBox_KeyDown(object sender, KeyEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Key == Key.Enter && DataContext is MainViewModel viewModel)
|
||||||
|
{
|
||||||
|
viewModel.SearchCommand.Execute(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 로그인 화면 디자인 개선
|
||||||
|
|
||||||
|
### 요청
|
||||||
|
- 가로 스크롤 디자인 개선
|
||||||
|
- 로그인 화면을 세련되게 변경
|
||||||
|
|
||||||
|
### 적용된 디자인
|
||||||
|
- 그라데이션 배경 (#1a1a2e → #16213e)
|
||||||
|
- 둥근 모서리 (CornerRadius="12")
|
||||||
|
- 그림자 효과 (DropShadowEffect)
|
||||||
|
- 로고 아이콘 (원형 그라데이션)
|
||||||
|
- 모던한 입력 필드 스타일
|
||||||
|
- 그라데이션 로그인 버튼
|
||||||
|
|
||||||
|
### 수정 파일
|
||||||
|
- `LoginWindow.xaml` - 전체 디자인 재구성
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 로그인 화면 짤림 현상 수정
|
||||||
|
|
||||||
|
### 요청
|
||||||
|
- 로그인 화면 위아래 짤림 현상 수정
|
||||||
|
|
||||||
|
### 해결 방법
|
||||||
|
- 외부 Border에 Margin="15" 추가
|
||||||
|
- 창 크기 500x420 → 540x440으로 확대
|
||||||
|
|
||||||
|
### 수정 파일
|
||||||
|
- `LoginWindow.xaml`
|
||||||
|
```xml
|
||||||
|
<Window Height="540" Width="440">
|
||||||
|
<Border Margin="15" CornerRadius="12">
|
||||||
|
<Border.Effect>
|
||||||
|
<DropShadowEffect BlurRadius="15" ShadowDepth="0" Opacity="0.5"/>
|
||||||
|
</Border.Effect>
|
||||||
|
...
|
||||||
|
</Border>
|
||||||
|
</Window>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 테마 버튼 동작 수정
|
||||||
|
|
||||||
|
### 요청
|
||||||
|
- 테마 버튼이 동작하지 않는 문제 수정
|
||||||
|
- 로그인 화면 제외 이전 디자인 유지
|
||||||
|
|
||||||
|
### 문제 원인
|
||||||
|
- MainWindow.xaml에 하드코딩된 색상 사용
|
||||||
|
- DynamicResource 대신 직접 색상값 (#1a1a2e 등) 사용
|
||||||
|
|
||||||
|
### 해결 방법
|
||||||
|
- MainWindow.xaml을 DynamicResource 사용하도록 복원
|
||||||
|
- LoginWindow.xaml은 새 디자인 유지 (하드코딩)
|
||||||
|
|
||||||
|
### 수정 파일
|
||||||
|
- `MainWindow.xaml`
|
||||||
|
```xml
|
||||||
|
<Window Background="{DynamicResource WindowBackgroundBrush}">
|
||||||
|
<Border Background="{DynamicResource SecondaryBrush}">
|
||||||
|
<DataGrid Style="{DynamicResource DefaultDataGridStyle}">
|
||||||
|
```
|
||||||
|
|
||||||
|
### 테마 전환 구조
|
||||||
|
1. **MainWindow.xaml** - 라디오 버튼 Command 바인딩
|
||||||
|
2. **MainViewModel.cs** - SetDefaultThemeCommand, SetLightThemeCommand
|
||||||
|
3. **SettingsService.cs** - ApplyTheme() 메서드로 ResourceDictionary 교체
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 최종 결과
|
||||||
|
|
||||||
|
### 완료된 기능
|
||||||
|
- ✅ MVVM 패턴 기반 WPF 애플리케이션
|
||||||
|
- ✅ 의존성 주입 (DI) 구현
|
||||||
|
- ✅ 로그인/회원관리 기능
|
||||||
|
- ✅ 테마 전환 (Dark/Light)
|
||||||
|
- ✅ 다국어 지원 (한국어/영어)
|
||||||
|
- ✅ 세련된 로그인 화면 디자인
|
||||||
|
- ✅ 반응형 레이아웃 (MinWidth/MinHeight)
|
||||||
|
- ✅ 엔터키 검색 기능
|
||||||
|
|
||||||
|
### 빌드 및 실행
|
||||||
|
```bash
|
||||||
|
cd src/WPFBeginner
|
||||||
|
dotnet build
|
||||||
|
dotnet run
|
||||||
|
```
|
||||||
|
|
||||||
|
### 기본 로그인 정보
|
||||||
|
- ID: admin
|
||||||
|
- Password: 0000
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*마지막 업데이트: 2025-12-29*
|
||||||
BIN
docs/WPF 기초를 위한 토이프로젝트.pptx
Normal file
75
docs/sampleApp/WPFBeginner.deps.json
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
{
|
||||||
|
"runtimeTarget": {
|
||||||
|
"name": ".NETCoreApp,Version=v8.0",
|
||||||
|
"signature": ""
|
||||||
|
},
|
||||||
|
"compilationOptions": {},
|
||||||
|
"targets": {
|
||||||
|
".NETCoreApp,Version=v8.0": {
|
||||||
|
"WPFBeginner/1.0.0": {
|
||||||
|
"dependencies": {
|
||||||
|
"CommunityToolkit.Mvvm": "8.2.2",
|
||||||
|
"Microsoft.Extensions.DependencyInjection": "8.0.0"
|
||||||
|
},
|
||||||
|
"runtime": {
|
||||||
|
"WPFBeginner.dll": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"CommunityToolkit.Mvvm/8.2.2": {
|
||||||
|
"runtime": {
|
||||||
|
"lib/net6.0/CommunityToolkit.Mvvm.dll": {
|
||||||
|
"assemblyVersion": "8.2.0.0",
|
||||||
|
"fileVersion": "8.2.2.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.DependencyInjection/8.0.0": {
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0"
|
||||||
|
},
|
||||||
|
"runtime": {
|
||||||
|
"lib/net8.0/Microsoft.Extensions.DependencyInjection.dll": {
|
||||||
|
"assemblyVersion": "8.0.0.0",
|
||||||
|
"fileVersion": "8.0.23.53103"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.DependencyInjection.Abstractions/8.0.0": {
|
||||||
|
"runtime": {
|
||||||
|
"lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
|
||||||
|
"assemblyVersion": "8.0.0.0",
|
||||||
|
"fileVersion": "8.0.23.53103"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"libraries": {
|
||||||
|
"WPFBeginner/1.0.0": {
|
||||||
|
"type": "project",
|
||||||
|
"serviceable": false,
|
||||||
|
"sha512": ""
|
||||||
|
},
|
||||||
|
"CommunityToolkit.Mvvm/8.2.2": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-r0g0k9tGYdrnz8R7T3x5UiokDffeevzK/2P/9SBL6fqLgN8B157MIi/bVUWI1KAz6ZorZrK9AdABCWUeXZZsvA==",
|
||||||
|
"path": "communitytoolkit.mvvm/8.2.2",
|
||||||
|
"hashPath": "communitytoolkit.mvvm.8.2.2.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.DependencyInjection/8.0.0": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-V8S3bsm50ig6JSyrbcJJ8bW2b9QLGouz+G1miK3UTaOWmMtFwNNNzUf4AleyDWUmTrWMLNnFSLEQtxmxgNQnNQ==",
|
||||||
|
"path": "microsoft.extensions.dependencyinjection/8.0.0",
|
||||||
|
"hashPath": "microsoft.extensions.dependencyinjection.8.0.0.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"Microsoft.Extensions.DependencyInjection.Abstractions/8.0.0": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-cjWrLkJXK0rs4zofsK4bSdg+jhDLTaxrkXu4gS6Y7MAlCvRyNNgwY/lJi5RDlQOnSZweHqoyvgvbdvQsRIW+hg==",
|
||||||
|
"path": "microsoft.extensions.dependencyinjection.abstractions/8.0.0",
|
||||||
|
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.8.0.0.nupkg.sha512"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
docs/sampleApp/WPFBeginner.pdb
Normal file
19
docs/sampleApp/WPFBeginner.runtimeconfig.json
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"runtimeOptions": {
|
||||||
|
"tfm": "net8.0",
|
||||||
|
"frameworks": [
|
||||||
|
{
|
||||||
|
"name": "Microsoft.NETCore.App",
|
||||||
|
"version": "8.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Microsoft.WindowsDesktop.App",
|
||||||
|
"version": "8.0.0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"configProperties": {
|
||||||
|
"System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
|
||||||
|
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
|
||||||
|
|
||||||
<!--Maximize Button-->
|
|
||||||
<Style x:Key="TiTleBarMaximizeButton" TargetType="{x:Type Button}">
|
|
||||||
<Setter Property="Background" Value="Transparent"/>
|
|
||||||
<Setter Property="Focusable" Value="False" />
|
|
||||||
<Setter Property="Template">
|
|
||||||
<Setter.Value>
|
|
||||||
<ControlTemplate TargetType="{x:Type Button}">
|
|
||||||
<Border Background="{TemplateBinding Background}">
|
|
||||||
<Path Fill="#FFB8B8B9" Height="14" Width="14" Canvas.Left="-7" Canvas.Top="5">
|
|
||||||
<Path.Style>
|
|
||||||
<Style TargetType="Path">
|
|
||||||
<Style.Triggers>
|
|
||||||
<DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" Value="Normal">
|
|
||||||
<!--<Setter Property="Data" Value="F1M3,5C3,5 3,11 3,11 3,11 9,11 9,11 9,11 9,5 9,5 9,5 3,5 3,5z M5,3C5,3,5,3.375,5,3.938L5,4 6,4C8,4 10,4 10,4 10,4 10,6 10,8L10,9 10.062,9C10.625,9 11,9 11,9 11,9 11,3 11,3 11,3 5,3 5,3z M4,2C4,2 12,2 12,2 12,2 12,10 12,10 12,10 11.5,10 10.75,10L10,10 10,10.75C10,11.5 10,12 10,12 10,12 2,12 2,12 2,12 2,4 2,4 2,4 2.5,4 3.25,4L4,4 4,3.25C4,2.5,4,2,4,2z"/>-->
|
|
||||||
<Setter Property="Data" Value="F1M3,3C3,3 3,11 3,11 3,11 11,11 11,11 11,11 11,3 11,3 11,3 3,3 3,3z M2,2C2,2 12,2 12,2 12,2 12,12 12,12 12,12 2,12 2,12 2,12 2,2 2,2z" />
|
|
||||||
</DataTrigger>
|
|
||||||
<DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" Value="Maximized">
|
|
||||||
<Setter Property="Data" Value="F1M3,5C3,5 3,11 3,11 3,11 9,11 9,11 9,11 9,5 9,5 9,5 3,5 3,5z M5,3C5,3 5,4 5,4 5,4 10,4 10,4 10,4 10,9 10,9 10,9 11,9 11,9 11,9 11,3 11,3 11,3 5,3 5,3z M4,2C4,2 12,2 12,2 12,2 12,10 12,10 12,10 10,10 10,10 10,10 10,12 10,12 10,12 2,12 2,12 2,12 2,4 2,4 2,4 4,4 4,4 4,4 4,2 4,2z"/>
|
|
||||||
</DataTrigger>
|
|
||||||
</Style.Triggers>
|
|
||||||
</Style>
|
|
||||||
</Path.Style>
|
|
||||||
</Path>
|
|
||||||
</Border>
|
|
||||||
</ControlTemplate>
|
|
||||||
</Setter.Value>
|
|
||||||
</Setter>
|
|
||||||
|
|
||||||
<Style.Triggers>
|
|
||||||
<Trigger Property="IsMouseOver" Value="True">
|
|
||||||
<Setter Property="Background" Value="#FF474D51"/>
|
|
||||||
</Trigger>
|
|
||||||
<Trigger Property="IsPressed" Value="True">
|
|
||||||
<Setter Property="Background" Value="#FF3D4347"/>
|
|
||||||
</Trigger>
|
|
||||||
<DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" Value="Normal">
|
|
||||||
<Setter Property="ToolTip" Value="Maximize"/>
|
|
||||||
</DataTrigger>
|
|
||||||
<DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" Value="Maximized">
|
|
||||||
<Setter Property="ToolTip" Value="Restore"/>
|
|
||||||
</DataTrigger>
|
|
||||||
</Style.Triggers>
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<!--Minimize Button-->
|
|
||||||
<Style x:Key="TiTleBarMinimizeButton" TargetType="{x:Type Button}">
|
|
||||||
<Setter Property="Background" Value="Transparent"/>
|
|
||||||
<Setter Property="Focusable" Value="False" />
|
|
||||||
<Setter Property="Template">
|
|
||||||
<Setter.Value>
|
|
||||||
<ControlTemplate TargetType="{x:Type Button}">
|
|
||||||
<Border Background="{TemplateBinding Background}">
|
|
||||||
<Path Data="F1M2,2C2,2 12,2 12,2 12,2 12,3 12,3 12,3 2,3 2,3 2,3 2,2 2,2z" Fill="#FFB8B8B9" Height="4" Canvas.Left="0" Canvas.Top="0" Width="13"/>
|
|
||||||
</Border>
|
|
||||||
</ControlTemplate>
|
|
||||||
</Setter.Value>
|
|
||||||
</Setter>
|
|
||||||
<Style.Triggers>
|
|
||||||
<Trigger Property="IsMouseOver" Value="True">
|
|
||||||
<Setter Property="Background" Value="#FF474D51"/>
|
|
||||||
</Trigger>
|
|
||||||
<Trigger Property="IsPressed" Value="True">
|
|
||||||
<Setter Property="Background" Value="#FF3D4347"/>
|
|
||||||
</Trigger>
|
|
||||||
</Style.Triggers>
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<!--Close Button-->
|
|
||||||
<Style x:Key="TiTleBarCloseButton" TargetType="{x:Type Button}">
|
|
||||||
<Setter Property="Background" Value="Transparent"/>
|
|
||||||
<Setter Property="Focusable" Value="False" />
|
|
||||||
<Setter Property="Template">
|
|
||||||
<Setter.Value>
|
|
||||||
<ControlTemplate TargetType="{x:Type Button}">
|
|
||||||
<Border Background="{TemplateBinding Background}">
|
|
||||||
<Path Data="F1M2,2C2,2,2.25,2,2.5,2L2.999,2 3,2 3,2.001 3.221,2.222C3.652,2.653,4.66,3.661,5.847,4.848L6.999,6 8.152,4.848C9.734,3.266,10.999,2,10.999,2L11,2.001 11,2C11,2 12,2 12,2 12,2 12,3 12,3 12,3 10.734,4.266 9.152,5.848L8,7 9.152,8.152C10.734,9.734 12,11 12,11 12,11 12,12 12,12 12,12 11,12 11,12L11,11.999 10.999,12C10.999,12,9.733,10.734,8.151,9.152L6.999,8 5.847,9.152C4.66,10.339,3.652,11.347,3.221,11.778L3,11.999 3,12 2.999,12C3,12 2,12 2,12 2,12 2,11 2,11 2,11 3.265,9.734 4.847,8.152L5.999,7 4.847,5.848C3.265,4.266,1.999,3,1.999,3L2,2.999 2,2.844C2,2.562,2,2,2,2z"
|
|
||||||
Fill="#FFB8B8B9" Height="13" Canvas.Left="0" Canvas.Top="0" Width="13"/>
|
|
||||||
</Border>
|
|
||||||
</ControlTemplate>
|
|
||||||
</Setter.Value>
|
|
||||||
</Setter>
|
|
||||||
<Style.Triggers>
|
|
||||||
<Trigger Property="IsMouseOver" Value="True">
|
|
||||||
<Setter Property="Background" Value="#FFF06251"/>
|
|
||||||
</Trigger>
|
|
||||||
<Trigger Property="IsPressed" Value="True">
|
|
||||||
<Setter Property="Background" Value="#FFED3F2B"/>
|
|
||||||
</Trigger>
|
|
||||||
</Style.Triggers>
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
</ResourceDictionary>
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="Colors.TitleBar.Title.Background" Color="#FF1E1E1E"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.TitleBar.Title.Foreground" Color="LightGreen"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.Section.HorizontalSeperator" Color="Cyan" Opacity="0.8"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.Main.Background" Color="#FF1E1E1E" />
|
|
||||||
<SolidColorBrush x:Key="Colors.SettingPopup.Background" Color="#FF383838" />
|
|
||||||
<SolidColorBrush x:Key="Colors.SettingPopup.BorderBrush" Color="#FF424242" />
|
|
||||||
<SolidColorBrush x:Key="Colors.SettingPopup.Foreground" Color="White" />
|
|
||||||
<SolidColorBrush x:Key="Colors.TextBox.Background" Color="#FF383838"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.TextBox.Foreground" Color="White"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.TextBox.BorderBrush" Color="#FF424242"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Foreground.Normal" Color="White"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Foreground.MouseOver" Color="Pink"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Foreground.MousePressed" Color="Coral"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.BorderBrush.Normal" Color="#FF1F1F1F"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.BorderBrush.MouseOver" Color="Pink"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.BorderBrush.MousePressed" Color="Coral"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Background.Normal" Color="#FF1F1F1F"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Background.MouseOver" Color="#FF1F1F1F"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Background.MousePressed" Color="#FF1F1F1F"/>
|
|
||||||
|
|
||||||
<LinearGradientBrush x:Key="Colors.DataGridButton.Background.Normal" StartPoint="0,0" EndPoint="0,1">
|
|
||||||
<GradientStop Color="#38301f" Offset="0.0"/>
|
|
||||||
<GradientStop Color="#4a3c2b" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#342e1d" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#342e1d" Offset="1.0"/>
|
|
||||||
</LinearGradientBrush>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="Colors.DataGridButton.Foreground.Normal" Color="White" />
|
|
||||||
<!--<SolidColorBrush x:Key="Colors.DataGridButton.Background.MouseOver" Color="#FFEB530C" Opacity="0.6" />-->
|
|
||||||
<LinearGradientBrush x:Key="Colors.DataGridButton.Background.MouseOver" StartPoint="0,0" EndPoint="0,1" Opacity="0.6">
|
|
||||||
<GradientStop Color="#38301f" Offset="0.0"/>
|
|
||||||
<GradientStop Color="#4a3c2b" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#342e1d" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#342e1d" Offset="1.0"/>
|
|
||||||
</LinearGradientBrush>
|
|
||||||
<SolidColorBrush x:Key="Colors.DataGridButton.Foreground.MouseOver" Color="Yellow" />
|
|
||||||
<LinearGradientBrush x:Key="Colors.DataGridButton.Background.Pressed" StartPoint="0,0" EndPoint="0,1" Opacity="0.8">
|
|
||||||
<GradientStop Color="#38301f" Offset="0.0"/>
|
|
||||||
<GradientStop Color="#4a3c2b" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#342e1d" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#342e1d" Offset="1.0"/>
|
|
||||||
</LinearGradientBrush>
|
|
||||||
<!--<SolidColorBrush x:Key="Colors.DataGridButton.Background.Pressed" Color="#FFEB530C" Opacity="0.8" />-->
|
|
||||||
<SolidColorBrush x:Key="Colors.DataGridButton.Foreground.Pressed" Color="LightSkyBlue" />
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="Colors.Images.OptionsMenu.Setting.Normal" Color="#FFB8B8B9"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.Images.OptionsMenu.Setting.Pressed" Color="#FFB8B8B9" Opacity="0.6"/>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="Colors.Images.OptionsMenu.Setting.Background.MouseOver" Color="#FF474D51"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.Images.OptionsMenu.Setting.Background.MousePressed" Color="#FF474D51"/>
|
|
||||||
|
|
||||||
</ResourceDictionary>
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="Colors.TitleBar.Title.Background" Color="#FFF0F0F0"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.TitleBar.Title.Foreground" Color="DarkSlateBlue"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.Section.HorizontalSeperator" Color="Gray" Opacity="0.8"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.Main.Background" Color="#FFF0F0F0" />
|
|
||||||
<SolidColorBrush x:Key="Colors.SettingPopup.Background" Color="#FFF5F5F5" />
|
|
||||||
<SolidColorBrush x:Key="Colors.SettingPopup.BorderBrush" Color="#FFDDDDDD" />
|
|
||||||
<SolidColorBrush x:Key="Colors.SettingPopup.Foreground" Color="Black" />
|
|
||||||
<SolidColorBrush x:Key="Colors.TextBox.Background" Color="#FFF5F5F5"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.TextBox.Foreground" Color="Black"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.TextBox.BorderBrush" Color="#FFDDDDDD"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Foreground.Normal" Color="Black"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Foreground.MouseOver" Color="MediumSlateBlue"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Foreground.MousePressed" Color="SlateBlue"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.BorderBrush.Normal" Color="#FFEEEEEE"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.BorderBrush.MouseOver" Color="MediumSlateBlue"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.BorderBrush.MousePressed" Color="SlateBlue"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Background.Normal" Color="#FFEEEEEE"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Background.MouseOver" Color="#FFE0E0E0"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Background.MousePressed" Color="#FFD6D6D6"/>
|
|
||||||
|
|
||||||
<LinearGradientBrush x:Key="Colors.DataGridButton.Background.Normal" StartPoint="0,0" EndPoint="0,1">
|
|
||||||
<GradientStop Color="#E3EAF3" Offset="0.0"/>
|
|
||||||
<GradientStop Color="#D4DFEA" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#C8D4E1" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#BFCCE0" Offset="1.0"/>
|
|
||||||
</LinearGradientBrush>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="Colors.DataGridButton.Foreground.Normal" Color="Black" />
|
|
||||||
<LinearGradientBrush x:Key="Colors.DataGridButton.Background.MouseOver" StartPoint="0,0" EndPoint="0,1" Opacity="0.6">
|
|
||||||
<GradientStop Color="#E3EAF3" Offset="0.0"/>
|
|
||||||
<GradientStop Color="#D4DFEA" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#C8D4E1" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#BFCCE0" Offset="1.0"/>
|
|
||||||
</LinearGradientBrush>
|
|
||||||
<SolidColorBrush x:Key="Colors.DataGridButton.Foreground.MouseOver" Color="DarkSlateBlue" />
|
|
||||||
<LinearGradientBrush x:Key="Colors.DataGridButton.Background.Pressed" StartPoint="0,0" EndPoint="0,1" Opacity="0.8">
|
|
||||||
<GradientStop Color="#E3EAF3" Offset="0.0"/>
|
|
||||||
<GradientStop Color="#D4DFEA" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#C8D4E1" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#BFCCE0" Offset="1.0"/>
|
|
||||||
</LinearGradientBrush>
|
|
||||||
<SolidColorBrush x:Key="Colors.DataGridButton.Foreground.Pressed" Color="CornflowerBlue" />
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="Colors.Images.OptionsMenu.Setting.Normal" Color="#FF6E6E70"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.Images.OptionsMenu.Setting.Pressed" Color="#FF6E6E70" Opacity="0.6"/>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="Colors.Images.OptionsMenu.Setting.Background.MouseOver" Color="#FFD3D3D5"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.Images.OptionsMenu.Setting.Background.MousePressed" Color="#FFD3D3D5"/>
|
|
||||||
</ResourceDictionary>
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
|
||||||
|
|
||||||
<DrawingImage x:Key="Images.OptionsMenu.Setting.Normal">
|
|
||||||
<DrawingImage.Drawing>
|
|
||||||
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
|
|
||||||
<GeometryDrawing Brush="{DynamicResource Colors.Images.OptionsMenu.Setting.Normal}" Geometry="F0 M24,24z M0,0z M10.1,1.3L10.1,1.1 12.7,1.1 12.7,1.3 13,2.6 13.2,3.7C14.2,3.9,15.1,4.3,15.9,4.8L16,4.8 17.7,3.5 17.8,3.4 18.1,3.4 18.9,4.2 19.7,5 19.7,5.3 19.6,5.4 19,6.2 18.4,7.1C18.9,7.9,19.3,8.8,19.6,9.8L19.6,9.9 20.5,10 20.7,10 21.7,10.2 21.9,10.2 21.9,12.8 21.7,12.8 20.7,13 19.6,13.2C19.4,14.2,19,15.1,18.5,15.9L19.8,17.6C19.8,17.6,19.8,17.7,19.9,17.7L19.9,18 19.1,18.8 18.3,19.6 18,19.6 17.9,19.5 16,18.4C15.2,18.9,14.2,19.3,13.3,19.5L13.3,19.6 13,21.7 13,21.9 10.4,21.9 10.4,21.7 10.2,20.5 10,19.4C9.1,19.2,8.2,18.8,7.4,18.3L7,18.4 5.3,19.7 5.2,19.8 4.9,19.8 4.1,19 3.3,18.2 3.3,17.9 3.4,17.8 4.2,16.7 4.6,16 4.8,15.7C4.4,15,4,14.2,3.8,13.3L3.4,13.2 1.4,12.9 1.2,12.9 1.2,10.3 1.4,10.3 3.5,9.99999999999999 3.8,9.9C4,8.99999999999999,4.3,8.2,4.8,7.4L4.1,6.4 3.3,5.4 3.2,5.3 3.2,5 4,4.1 4.8,3.3 5.1,3.3 5.2,3.4 7,4.7 7.2,4.9C8,4.3,8.8,3.9,9.8,3.7L10,2.6 10.1,1.3z M13.9,1.3L14.1,2.8C14.7,3,15.3,3.2,15.8,3.5L17,2.6C17.1,2.5 17.4,2.3 17.7,2.2 18,2.1 18.4,2.2 18.8,2.5L19.6,3.3 20.4,4.1C20.7,4.4 20.8,4.8 20.7,5.2 20.6,5.5 20.5,5.7 20.3,5.9L19.5,7C19.8,7.6,20.1,8.2,20.3,8.8L21.7,9C21.9,9 22.2,9.1 22.4,9.2 22.7,9.4 22.9,9.7 22.9,10.2L22.9,12.6C22.9,13.1 22.7,13.4 22.4,13.6 22.2,13.8 21.9,13.8 21.7,13.8L20.3,14C20.1,14.6,19.9,15.2,19.6,15.7L20.4,16.8C20.5,16.9 20.7,17.2 20.8,17.5 20.9,17.8 20.8,18.2 20.5,18.6L19.7,19.4 18.9,20.2C18.6,20.5 18.2,20.6 17.8,20.5 17.5,20.4 17.3,20.3 17.1,20.1L15.9,19.2C15.3,19.5,14.7,19.7,14.1,19.9L13.9,21.4C13.9,21.6 13.8,21.9 13.7,22.1 13.5,22.4 13.2,22.6 12.7,22.6L10.3,22.6C9.8,22.6 9.5,22.4 9.3,22.1 9.1,21.9 9.1,21.6 9.1,21.4L8.9,19.8C8.3,19.6,7.8,19.4,7.2,19.1L5.9,20.1C5.8,20.2 5.5,20.4 5.2,20.5 4.9,20.6 4.5,20.5 4.1,20.2L3.3,19.4 2.5,18.6C2.2,18.3 2.1,17.9 2.2,17.5 2.3,17.2 2.4,17 2.6,16.8L3.6,15.4C3.4,14.9,3.2,14.5,3,14L1.2,14C1,14 0.7,13.9 0.5,13.8 0.2,13.6 0,13.3 0,12.8L0,10.4C0,9.9 0.2,9.6 0.5,9.4 0.8,9.2 1,9.2 1.2,9.2L3,8.9 3.6,7.4 2.5,6C2.4,5.8 2.2,5.6 2.2,5.3 2.1,5 2.2,4.6 2.5,4.2L3.3,3.4 4.1,2.6C4.4,2.3 4.8,2.2 5.2,2.3 5.5,2.4 5.7,2.5 5.9,2.7L7.2,3.7C7.7,3.4,8.2,3.2,8.8,3L9,1.4C9,1.2 9.1,0.9 9.2,0.7 9.5,0.3 9.8,0 10.3,0L12.7,0C13.2,0 13.5,0.2 13.7,0.5 13.8,0.8 13.9,1.1 13.9,1.3z" />
|
|
||||||
<GeometryDrawing>
|
|
||||||
<GeometryDrawing.Pen>
|
|
||||||
<Pen Brush="{DynamicResource Colors.Images.OptionsMenu.Setting.Normal}" Thickness="1" StartLineCap="Flat" EndLineCap="Flat" LineJoin="Miter" />
|
|
||||||
</GeometryDrawing.Pen>
|
|
||||||
<GeometryDrawing.Geometry>
|
|
||||||
<EllipseGeometry RadiusX="3.4" RadiusY="3.4" Center="11.5,11.5" />
|
|
||||||
</GeometryDrawing.Geometry>
|
|
||||||
</GeometryDrawing>
|
|
||||||
</DrawingGroup>
|
|
||||||
</DrawingImage.Drawing>
|
|
||||||
</DrawingImage>
|
|
||||||
|
|
||||||
<DrawingImage x:Key="Images.OptionsMenu.Setting.Pressed">
|
|
||||||
<DrawingImage.Drawing>
|
|
||||||
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
|
|
||||||
<GeometryDrawing Brush="{DynamicResource Colors.Images.OptionsMenu.Setting.Pressed}" Geometry="F0 M24,24z M0,0z M10.1,1.3L10.1,1.1 12.7,1.1 12.7,1.3 13,2.6 13.2,3.7C14.2,3.9,15.1,4.3,15.9,4.8L16,4.8 17.7,3.5 17.8,3.4 18.1,3.4 18.9,4.2 19.7,5 19.7,5.3 19.6,5.4 19,6.2 18.4,7.1C18.9,7.9,19.3,8.8,19.6,9.8L19.6,9.9 20.5,10 20.7,10 21.7,10.2 21.9,10.2 21.9,12.8 21.7,12.8 20.7,13 19.6,13.2C19.4,14.2,19,15.1,18.5,15.9L19.8,17.6C19.8,17.6,19.8,17.7,19.9,17.7L19.9,18 19.1,18.8 18.3,19.6 18,19.6 17.9,19.5 16,18.4C15.2,18.9,14.2,19.3,13.3,19.5L13.3,19.6 13,21.7 13,21.9 10.4,21.9 10.4,21.7 10.2,20.5 10,19.4C9.1,19.2,8.2,18.8,7.4,18.3L7,18.4 5.3,19.7 5.2,19.8 4.9,19.8 4.1,19 3.3,18.2 3.3,17.9 3.4,17.8 4.2,16.7 4.6,16 4.8,15.7C4.4,15,4,14.2,3.8,13.3L3.4,13.2 1.4,12.9 1.2,12.9 1.2,10.3 1.4,10.3 3.5,9.99999999999999 3.8,9.9C4,8.99999999999999,4.3,8.2,4.8,7.4L4.1,6.4 3.3,5.4 3.2,5.3 3.2,5 4,4.1 4.8,3.3 5.1,3.3 5.2,3.4 7,4.7 7.2,4.9C8,4.3,8.8,3.9,9.8,3.7L10,2.6 10.1,1.3z M13.9,1.3L14.1,2.8C14.7,3,15.3,3.2,15.8,3.5L17,2.6C17.1,2.5 17.4,2.3 17.7,2.2 18,2.1 18.4,2.2 18.8,2.5L19.6,3.3 20.4,4.1C20.7,4.4 20.8,4.8 20.7,5.2 20.6,5.5 20.5,5.7 20.3,5.9L19.5,7C19.8,7.6,20.1,8.2,20.3,8.8L21.7,9C21.9,9 22.2,9.1 22.4,9.2 22.7,9.4 22.9,9.7 22.9,10.2L22.9,12.6C22.9,13.1 22.7,13.4 22.4,13.6 22.2,13.8 21.9,13.8 21.7,13.8L20.3,14C20.1,14.6,19.9,15.2,19.6,15.7L20.4,16.8C20.5,16.9 20.7,17.2 20.8,17.5 20.9,17.8 20.8,18.2 20.5,18.6L19.7,19.4 18.9,20.2C18.6,20.5 18.2,20.6 17.8,20.5 17.5,20.4 17.3,20.3 17.1,20.1L15.9,19.2C15.3,19.5,14.7,19.7,14.1,19.9L13.9,21.4C13.9,21.6 13.8,21.9 13.7,22.1 13.5,22.4 13.2,22.6 12.7,22.6L10.3,22.6C9.8,22.6 9.5,22.4 9.3,22.1 9.1,21.9 9.1,21.6 9.1,21.4L8.9,19.8C8.3,19.6,7.8,19.4,7.2,19.1L5.9,20.1C5.8,20.2 5.5,20.4 5.2,20.5 4.9,20.6 4.5,20.5 4.1,20.2L3.3,19.4 2.5,18.6C2.2,18.3 2.1,17.9 2.2,17.5 2.3,17.2 2.4,17 2.6,16.8L3.6,15.4C3.4,14.9,3.2,14.5,3,14L1.2,14C1,14 0.7,13.9 0.5,13.8 0.2,13.6 0,13.3 0,12.8L0,10.4C0,9.9 0.2,9.6 0.5,9.4 0.8,9.2 1,9.2 1.2,9.2L3,8.9 3.6,7.4 2.5,6C2.4,5.8 2.2,5.6 2.2,5.3 2.1,5 2.2,4.6 2.5,4.2L3.3,3.4 4.1,2.6C4.4,2.3 4.8,2.2 5.2,2.3 5.5,2.4 5.7,2.5 5.9,2.7L7.2,3.7C7.7,3.4,8.2,3.2,8.8,3L9,1.4C9,1.2 9.1,0.9 9.2,0.7 9.5,0.3 9.8,0 10.3,0L12.7,0C13.2,0 13.5,0.2 13.7,0.5 13.8,0.8 13.9,1.1 13.9,1.3z" />
|
|
||||||
<GeometryDrawing>
|
|
||||||
<GeometryDrawing.Pen>
|
|
||||||
<Pen Brush="{DynamicResource Colors.Images.OptionsMenu.Setting.Pressed}" Thickness="1" StartLineCap="Flat" EndLineCap="Flat" LineJoin="Miter" />
|
|
||||||
</GeometryDrawing.Pen>
|
|
||||||
<GeometryDrawing.Geometry>
|
|
||||||
<EllipseGeometry RadiusX="3.4" RadiusY="3.4" Center="11.5,11.5" />
|
|
||||||
</GeometryDrawing.Geometry>
|
|
||||||
</GeometryDrawing>
|
|
||||||
</DrawingGroup>
|
|
||||||
</DrawingImage.Drawing>
|
|
||||||
</DrawingImage>
|
|
||||||
|
|
||||||
</ResourceDictionary>
|
|
||||||
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 24 KiB |
16
src/WPFBeginner/App.xaml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<Application x:Class="WPFBeginner.App"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="clr-namespace:WPFBeginner"
|
||||||
|
xmlns:converters="clr-namespace:WPFBeginner.Converters">
|
||||||
|
<Application.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<ResourceDictionary Source="Resources/Themes/DefaultTheme.xaml"/>
|
||||||
|
<ResourceDictionary Source="Resources/Languages/ko-KR.xaml"/>
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
|
||||||
|
<converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</Application.Resources>
|
||||||
|
</Application>
|
||||||
52
src/WPFBeginner/App.xaml.cs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
using System.Windows;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using WPFBeginner.Services;
|
||||||
|
using WPFBeginner.ViewModels;
|
||||||
|
using WPFBeginner.Views;
|
||||||
|
|
||||||
|
namespace WPFBeginner;
|
||||||
|
|
||||||
|
public partial class App : Application
|
||||||
|
{
|
||||||
|
private static IServiceProvider? _serviceProvider;
|
||||||
|
|
||||||
|
protected override void OnStartup(StartupEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnStartup(e);
|
||||||
|
|
||||||
|
var services = new ServiceCollection();
|
||||||
|
ConfigureServices(services);
|
||||||
|
_serviceProvider = services.BuildServiceProvider();
|
||||||
|
|
||||||
|
// Load settings first
|
||||||
|
var settingsService = _serviceProvider.GetRequiredService<ISettingsService>();
|
||||||
|
settingsService.Load();
|
||||||
|
|
||||||
|
// Show login window
|
||||||
|
var loginWindow = new LoginWindow();
|
||||||
|
loginWindow.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
// Services
|
||||||
|
services.AddSingleton<ISettingsService, SettingsService>();
|
||||||
|
services.AddSingleton<IMemberService, MemberService>();
|
||||||
|
|
||||||
|
// ViewModels
|
||||||
|
services.AddTransient<LoginViewModel>();
|
||||||
|
services.AddTransient<MainViewModel>();
|
||||||
|
services.AddTransient<RegistViewModel>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T GetService<T>() where T : class
|
||||||
|
{
|
||||||
|
if (_serviceProvider == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Service provider is not initialized.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return _serviceProvider.GetRequiredService<T>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
|
||||||
[assembly: ThemeInfo(
|
[assembly:ThemeInfo(
|
||||||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||||
//(used if a resource is not found in the page,
|
//(used if a resource is not found in the page,
|
||||||
// or application resource dictionaries)
|
// or application resource dictionaries)
|
||||||
22
src/WPFBeginner/Controls/InputPanel.xaml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<UserControl x:Class="WPFBeginner.Controls.InputPanel"
|
||||||
|
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"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
x:Name="Root">
|
||||||
|
|
||||||
|
<StackPanel>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<Label Content="{Binding LabelText, ElementName=Root}"
|
||||||
|
Style="{DynamicResource DefaultLabelStyle}"/>
|
||||||
|
<TextBlock Text="*"
|
||||||
|
Foreground="{DynamicResource ErrorBrush}"
|
||||||
|
Visibility="{Binding IsRequired, ElementName=Root, Converter={StaticResource BoolToVisibilityConverter}}"
|
||||||
|
Margin="2,0,0,0"
|
||||||
|
VerticalAlignment="Center"/>
|
||||||
|
</StackPanel>
|
||||||
|
<TextBox Text="{Binding Text, ElementName=Root, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
Style="{DynamicResource DefaultTextBoxStyle}"/>
|
||||||
|
</StackPanel>
|
||||||
|
</UserControl>
|
||||||
53
src/WPFBeginner/Controls/InputPanel.xaml.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
|
||||||
|
namespace WPFBeginner.Controls;
|
||||||
|
|
||||||
|
public partial class InputPanel : UserControl
|
||||||
|
{
|
||||||
|
public static readonly DependencyProperty LabelTextProperty =
|
||||||
|
DependencyProperty.Register(
|
||||||
|
nameof(LabelText),
|
||||||
|
typeof(string),
|
||||||
|
typeof(InputPanel),
|
||||||
|
new PropertyMetadata(string.Empty));
|
||||||
|
|
||||||
|
public static readonly DependencyProperty TextProperty =
|
||||||
|
DependencyProperty.Register(
|
||||||
|
nameof(Text),
|
||||||
|
typeof(string),
|
||||||
|
typeof(InputPanel),
|
||||||
|
new FrameworkPropertyMetadata(
|
||||||
|
string.Empty,
|
||||||
|
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
|
||||||
|
|
||||||
|
public static readonly DependencyProperty IsRequiredProperty =
|
||||||
|
DependencyProperty.Register(
|
||||||
|
nameof(IsRequired),
|
||||||
|
typeof(bool),
|
||||||
|
typeof(InputPanel),
|
||||||
|
new PropertyMetadata(false));
|
||||||
|
|
||||||
|
public string LabelText
|
||||||
|
{
|
||||||
|
get => (string)GetValue(LabelTextProperty);
|
||||||
|
set => SetValue(LabelTextProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Text
|
||||||
|
{
|
||||||
|
get => (string)GetValue(TextProperty);
|
||||||
|
set => SetValue(TextProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsRequired
|
||||||
|
{
|
||||||
|
get => (bool)GetValue(IsRequiredProperty);
|
||||||
|
set => SetValue(IsRequiredProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputPanel()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/WPFBeginner/Converters/BoolToVisibilityConverter.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Data;
|
||||||
|
|
||||||
|
namespace WPFBeginner.Converters;
|
||||||
|
|
||||||
|
public class BoolToVisibilityConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value is bool boolValue)
|
||||||
|
{
|
||||||
|
return boolValue ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
return Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value is Visibility visibility)
|
||||||
|
{
|
||||||
|
return visibility == Visibility.Visible;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/WPFBeginner/Models/AppSettings.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
namespace WPFBeginner.Models;
|
||||||
|
|
||||||
|
public class AppSettings
|
||||||
|
{
|
||||||
|
public LoginSettings Login { get; set; } = new();
|
||||||
|
public string Language { get; set; } = "ko-KR";
|
||||||
|
public string Theme { get; set; } = "DefaultTheme";
|
||||||
|
public List<Member> DefaultMembers { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LoginSettings
|
||||||
|
{
|
||||||
|
public string User { get; set; } = "admin";
|
||||||
|
public string Password { get; set; } = "0000";
|
||||||
|
}
|
||||||
33
src/WPFBeginner/Models/Member.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
|
||||||
|
namespace WPFBeginner.Models;
|
||||||
|
|
||||||
|
public partial class Member : ObservableObject
|
||||||
|
{
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _name = string.Empty;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _call = string.Empty;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _eMail = string.Empty;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _no = string.Empty;
|
||||||
|
|
||||||
|
public Member() { }
|
||||||
|
|
||||||
|
public Member(string name, string call, string email, string no)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Call = call;
|
||||||
|
EMail = email;
|
||||||
|
No = no;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Member Clone()
|
||||||
|
{
|
||||||
|
return new Member(Name, Call, EMail, No);
|
||||||
|
}
|
||||||
|
}
|
||||||
53
src/WPFBeginner/Resources/Languages/en-US.xaml
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||||
|
|
||||||
|
<!-- Login Window -->
|
||||||
|
<system:String x:Key="Login_Title">Login</system:String>
|
||||||
|
<system:String x:Key="Login_Welcome">Welcome</system:String>
|
||||||
|
<system:String x:Key="Login_UserId">User ID</system:String>
|
||||||
|
<system:String x:Key="Login_Password">Password</system:String>
|
||||||
|
<system:String x:Key="Login_LoginButton">Login</system:String>
|
||||||
|
<system:String x:Key="Login_Error">Invalid ID or Password</system:String>
|
||||||
|
|
||||||
|
<!-- Main Window -->
|
||||||
|
<system:String x:Key="Main_Title">Member Management</system:String>
|
||||||
|
<system:String x:Key="Main_Search">Search</system:String>
|
||||||
|
<system:String x:Key="Main_SearchPlaceholder">Enter search keyword</system:String>
|
||||||
|
<system:String x:Key="Main_Add">Add</system:String>
|
||||||
|
<system:String x:Key="Main_Delete">Delete</system:String>
|
||||||
|
<system:String x:Key="Main_Reset">Reset</system:String>
|
||||||
|
<system:String x:Key="Main_Settings">Settings</system:String>
|
||||||
|
<system:String x:Key="Main_NoResults">No results found</system:String>
|
||||||
|
|
||||||
|
<!-- Main Window - DataGrid -->
|
||||||
|
<system:String x:Key="Main_Column_Name">Name</system:String>
|
||||||
|
<system:String x:Key="Main_Column_Call">Phone</system:String>
|
||||||
|
<system:String x:Key="Main_Column_Email">Email</system:String>
|
||||||
|
<system:String x:Key="Main_Column_No">Employee No.</system:String>
|
||||||
|
|
||||||
|
<!-- Main Window - Settings -->
|
||||||
|
<system:String x:Key="Settings_Language">Language</system:String>
|
||||||
|
<system:String x:Key="Settings_Korean">한국어</system:String>
|
||||||
|
<system:String x:Key="Settings_English">English</system:String>
|
||||||
|
<system:String x:Key="Settings_Theme">Theme</system:String>
|
||||||
|
<system:String x:Key="Settings_DefaultTheme">Default (Dark)</system:String>
|
||||||
|
<system:String x:Key="Settings_LightTheme">Light</system:String>
|
||||||
|
|
||||||
|
<!-- Registration Window -->
|
||||||
|
<system:String x:Key="Regist_Title">Member Registration</system:String>
|
||||||
|
<system:String x:Key="Regist_Name">Name</system:String>
|
||||||
|
<system:String x:Key="Regist_Call">Phone</system:String>
|
||||||
|
<system:String x:Key="Regist_Email">Email</system:String>
|
||||||
|
<system:String x:Key="Regist_No">Employee No.</system:String>
|
||||||
|
<system:String x:Key="Regist_Register">Register</system:String>
|
||||||
|
<system:String x:Key="Regist_Cancel">Cancel</system:String>
|
||||||
|
<system:String x:Key="Regist_NameRequired">Name is required</system:String>
|
||||||
|
<system:String x:Key="Regist_EmailRequired">Email is required</system:String>
|
||||||
|
|
||||||
|
<!-- Common -->
|
||||||
|
<system:String x:Key="Common_Close">Close</system:String>
|
||||||
|
<system:String x:Key="Common_OK">OK</system:String>
|
||||||
|
<system:String x:Key="Common_Cancel">Cancel</system:String>
|
||||||
|
|
||||||
|
</ResourceDictionary>
|
||||||
53
src/WPFBeginner/Resources/Languages/ko-KR.xaml
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||||
|
|
||||||
|
<!-- Login Window -->
|
||||||
|
<system:String x:Key="Login_Title">로그인</system:String>
|
||||||
|
<system:String x:Key="Login_Welcome">환영합니다</system:String>
|
||||||
|
<system:String x:Key="Login_UserId">아이디</system:String>
|
||||||
|
<system:String x:Key="Login_Password">비밀번호</system:String>
|
||||||
|
<system:String x:Key="Login_LoginButton">로그인</system:String>
|
||||||
|
<system:String x:Key="Login_Error">아이디 또는 비밀번호가 틀렸습니다</system:String>
|
||||||
|
|
||||||
|
<!-- Main Window -->
|
||||||
|
<system:String x:Key="Main_Title">회원 관리</system:String>
|
||||||
|
<system:String x:Key="Main_Search">검색</system:String>
|
||||||
|
<system:String x:Key="Main_SearchPlaceholder">검색어를 입력하세요</system:String>
|
||||||
|
<system:String x:Key="Main_Add">추가</system:String>
|
||||||
|
<system:String x:Key="Main_Delete">삭제</system:String>
|
||||||
|
<system:String x:Key="Main_Reset">초기화</system:String>
|
||||||
|
<system:String x:Key="Main_Settings">설정</system:String>
|
||||||
|
<system:String x:Key="Main_NoResults">검색 결과가 없습니다</system:String>
|
||||||
|
|
||||||
|
<!-- Main Window - DataGrid -->
|
||||||
|
<system:String x:Key="Main_Column_Name">이름</system:String>
|
||||||
|
<system:String x:Key="Main_Column_Call">연락처</system:String>
|
||||||
|
<system:String x:Key="Main_Column_Email">이메일</system:String>
|
||||||
|
<system:String x:Key="Main_Column_No">사번</system:String>
|
||||||
|
|
||||||
|
<!-- Main Window - Settings -->
|
||||||
|
<system:String x:Key="Settings_Language">언어</system:String>
|
||||||
|
<system:String x:Key="Settings_Korean">한국어</system:String>
|
||||||
|
<system:String x:Key="Settings_English">English</system:String>
|
||||||
|
<system:String x:Key="Settings_Theme">테마</system:String>
|
||||||
|
<system:String x:Key="Settings_DefaultTheme">기본 (어두운)</system:String>
|
||||||
|
<system:String x:Key="Settings_LightTheme">밝은</system:String>
|
||||||
|
|
||||||
|
<!-- Registration Window -->
|
||||||
|
<system:String x:Key="Regist_Title">회원 등록</system:String>
|
||||||
|
<system:String x:Key="Regist_Name">이름</system:String>
|
||||||
|
<system:String x:Key="Regist_Call">연락처</system:String>
|
||||||
|
<system:String x:Key="Regist_Email">이메일</system:String>
|
||||||
|
<system:String x:Key="Regist_No">사번</system:String>
|
||||||
|
<system:String x:Key="Regist_Register">등록</system:String>
|
||||||
|
<system:String x:Key="Regist_Cancel">취소</system:String>
|
||||||
|
<system:String x:Key="Regist_NameRequired">이름은 필수입니다</system:String>
|
||||||
|
<system:String x:Key="Regist_EmailRequired">이메일은 필수입니다</system:String>
|
||||||
|
|
||||||
|
<!-- Common -->
|
||||||
|
<system:String x:Key="Common_Close">닫기</system:String>
|
||||||
|
<system:String x:Key="Common_OK">확인</system:String>
|
||||||
|
<system:String x:Key="Common_Cancel">취소</system:String>
|
||||||
|
|
||||||
|
</ResourceDictionary>
|
||||||
192
src/WPFBeginner/Resources/Themes/DefaultTheme.xaml
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
|
|
||||||
|
<!-- Colors -->
|
||||||
|
<Color x:Key="PrimaryColor">#2D2D30</Color>
|
||||||
|
<Color x:Key="SecondaryColor">#3E3E42</Color>
|
||||||
|
<Color x:Key="AccentColor">#007ACC</Color>
|
||||||
|
<Color x:Key="TextColor">#FFFFFF</Color>
|
||||||
|
<Color x:Key="SubTextColor">#A0A0A0</Color>
|
||||||
|
<Color x:Key="BorderColor">#555555</Color>
|
||||||
|
<Color x:Key="ErrorColor">#FF5555</Color>
|
||||||
|
<Color x:Key="SuccessColor">#55FF55</Color>
|
||||||
|
|
||||||
|
<!-- Brushes -->
|
||||||
|
<SolidColorBrush x:Key="PrimaryBrush" Color="{StaticResource PrimaryColor}"/>
|
||||||
|
<SolidColorBrush x:Key="SecondaryBrush" Color="{StaticResource SecondaryColor}"/>
|
||||||
|
<SolidColorBrush x:Key="AccentBrush" Color="{StaticResource AccentColor}"/>
|
||||||
|
<SolidColorBrush x:Key="TextBrush" Color="{StaticResource TextColor}"/>
|
||||||
|
<SolidColorBrush x:Key="SubTextBrush" Color="{StaticResource SubTextColor}"/>
|
||||||
|
<SolidColorBrush x:Key="BorderBrush" Color="{StaticResource BorderColor}"/>
|
||||||
|
<SolidColorBrush x:Key="ErrorBrush" Color="{StaticResource ErrorColor}"/>
|
||||||
|
<SolidColorBrush x:Key="SuccessBrush" Color="{StaticResource SuccessColor}"/>
|
||||||
|
|
||||||
|
<!-- Window Background -->
|
||||||
|
<SolidColorBrush x:Key="WindowBackgroundBrush" Color="{StaticResource PrimaryColor}"/>
|
||||||
|
|
||||||
|
<!-- Button Style -->
|
||||||
|
<Style x:Key="PrimaryButtonStyle" TargetType="Button">
|
||||||
|
<Setter Property="Background" Value="{StaticResource AccentBrush}"/>
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource TextBrush}"/>
|
||||||
|
<Setter Property="BorderThickness" Value="0"/>
|
||||||
|
<Setter Property="Padding" Value="15,8"/>
|
||||||
|
<Setter Property="Cursor" Value="Hand"/>
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Border Background="{TemplateBinding Background}"
|
||||||
|
CornerRadius="4"
|
||||||
|
Padding="{TemplateBinding Padding}">
|
||||||
|
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
</Border>
|
||||||
|
<ControlTemplate.Triggers>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Setter Property="Background" Value="#1A8AD4"/>
|
||||||
|
</Trigger>
|
||||||
|
<Trigger Property="IsPressed" Value="True">
|
||||||
|
<Setter Property="Background" Value="#005A9E"/>
|
||||||
|
</Trigger>
|
||||||
|
</ControlTemplate.Triggers>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style x:Key="SecondaryButtonStyle" TargetType="Button">
|
||||||
|
<Setter Property="Background" Value="{StaticResource SecondaryBrush}"/>
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource TextBrush}"/>
|
||||||
|
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/>
|
||||||
|
<Setter Property="BorderThickness" Value="1"/>
|
||||||
|
<Setter Property="Padding" Value="15,8"/>
|
||||||
|
<Setter Property="Cursor" Value="Hand"/>
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Border Background="{TemplateBinding Background}"
|
||||||
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
CornerRadius="4"
|
||||||
|
Padding="{TemplateBinding Padding}">
|
||||||
|
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
</Border>
|
||||||
|
<ControlTemplate.Triggers>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Setter Property="Background" Value="#4E4E52"/>
|
||||||
|
</Trigger>
|
||||||
|
</ControlTemplate.Triggers>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<!-- TextBox Style -->
|
||||||
|
<Style x:Key="DefaultTextBoxStyle" TargetType="TextBox">
|
||||||
|
<Setter Property="Background" Value="{StaticResource SecondaryBrush}"/>
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource TextBrush}"/>
|
||||||
|
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/>
|
||||||
|
<Setter Property="BorderThickness" Value="1"/>
|
||||||
|
<Setter Property="Padding" Value="8,6"/>
|
||||||
|
<Setter Property="CaretBrush" Value="{StaticResource TextBrush}"/>
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="TextBox">
|
||||||
|
<Border Background="{TemplateBinding Background}"
|
||||||
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
CornerRadius="4">
|
||||||
|
<ScrollViewer x:Name="PART_ContentHost" Margin="{TemplateBinding Padding}"/>
|
||||||
|
</Border>
|
||||||
|
<ControlTemplate.Triggers>
|
||||||
|
<Trigger Property="IsFocused" Value="True">
|
||||||
|
<Setter Property="BorderBrush" Value="{StaticResource AccentBrush}"/>
|
||||||
|
</Trigger>
|
||||||
|
</ControlTemplate.Triggers>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<!-- PasswordBox Style -->
|
||||||
|
<Style x:Key="DefaultPasswordBoxStyle" TargetType="PasswordBox">
|
||||||
|
<Setter Property="Background" Value="{StaticResource SecondaryBrush}"/>
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource TextBrush}"/>
|
||||||
|
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/>
|
||||||
|
<Setter Property="BorderThickness" Value="1"/>
|
||||||
|
<Setter Property="Padding" Value="8,6"/>
|
||||||
|
<Setter Property="CaretBrush" Value="{StaticResource TextBrush}"/>
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="PasswordBox">
|
||||||
|
<Border Background="{TemplateBinding Background}"
|
||||||
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
CornerRadius="4">
|
||||||
|
<ScrollViewer x:Name="PART_ContentHost" Margin="{TemplateBinding Padding}"/>
|
||||||
|
</Border>
|
||||||
|
<ControlTemplate.Triggers>
|
||||||
|
<Trigger Property="IsFocused" Value="True">
|
||||||
|
<Setter Property="BorderBrush" Value="{StaticResource AccentBrush}"/>
|
||||||
|
</Trigger>
|
||||||
|
</ControlTemplate.Triggers>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<!-- Label Style -->
|
||||||
|
<Style x:Key="DefaultLabelStyle" TargetType="Label">
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource TextBrush}"/>
|
||||||
|
<Setter Property="Padding" Value="0,0,0,4"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<!-- DataGrid Style -->
|
||||||
|
<Style x:Key="DefaultDataGridStyle" TargetType="DataGrid">
|
||||||
|
<Setter Property="Background" Value="{StaticResource SecondaryBrush}"/>
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource TextBrush}"/>
|
||||||
|
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/>
|
||||||
|
<Setter Property="BorderThickness" Value="1"/>
|
||||||
|
<Setter Property="RowBackground" Value="{StaticResource SecondaryBrush}"/>
|
||||||
|
<Setter Property="AlternatingRowBackground" Value="{StaticResource PrimaryBrush}"/>
|
||||||
|
<Setter Property="GridLinesVisibility" Value="Horizontal"/>
|
||||||
|
<Setter Property="HorizontalGridLinesBrush" Value="{StaticResource BorderBrush}"/>
|
||||||
|
<Setter Property="HeadersVisibility" Value="Column"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="DataGridColumnHeader">
|
||||||
|
<Setter Property="Background" Value="{StaticResource PrimaryBrush}"/>
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource TextBrush}"/>
|
||||||
|
<Setter Property="Padding" Value="10,8"/>
|
||||||
|
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/>
|
||||||
|
<Setter Property="BorderThickness" Value="0,0,1,1"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="DataGridCell">
|
||||||
|
<Setter Property="Padding" Value="10,6"/>
|
||||||
|
<Setter Property="BorderThickness" Value="0"/>
|
||||||
|
<Style.Triggers>
|
||||||
|
<Trigger Property="IsSelected" Value="True">
|
||||||
|
<Setter Property="Background" Value="{StaticResource AccentBrush}"/>
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource TextBrush}"/>
|
||||||
|
</Trigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="DataGridRow">
|
||||||
|
<Setter Property="Background" Value="Transparent"/>
|
||||||
|
<Style.Triggers>
|
||||||
|
<Trigger Property="IsSelected" Value="True">
|
||||||
|
<Setter Property="Background" Value="{StaticResource AccentBrush}"/>
|
||||||
|
</Trigger>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Setter Property="Background" Value="#3E3E42"/>
|
||||||
|
</Trigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<!-- RadioButton Style -->
|
||||||
|
<Style x:Key="DefaultRadioButtonStyle" TargetType="RadioButton">
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource TextBrush}"/>
|
||||||
|
<Setter Property="Margin" Value="0,4"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
</ResourceDictionary>
|
||||||
192
src/WPFBeginner/Resources/Themes/LightTheme.xaml
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
|
|
||||||
|
<!-- Colors -->
|
||||||
|
<Color x:Key="PrimaryColor">#FFFFFF</Color>
|
||||||
|
<Color x:Key="SecondaryColor">#F5F5F5</Color>
|
||||||
|
<Color x:Key="AccentColor">#007ACC</Color>
|
||||||
|
<Color x:Key="TextColor">#1E1E1E</Color>
|
||||||
|
<Color x:Key="SubTextColor">#666666</Color>
|
||||||
|
<Color x:Key="BorderColor">#CCCCCC</Color>
|
||||||
|
<Color x:Key="ErrorColor">#D32F2F</Color>
|
||||||
|
<Color x:Key="SuccessColor">#388E3C</Color>
|
||||||
|
|
||||||
|
<!-- Brushes -->
|
||||||
|
<SolidColorBrush x:Key="PrimaryBrush" Color="{StaticResource PrimaryColor}"/>
|
||||||
|
<SolidColorBrush x:Key="SecondaryBrush" Color="{StaticResource SecondaryColor}"/>
|
||||||
|
<SolidColorBrush x:Key="AccentBrush" Color="{StaticResource AccentColor}"/>
|
||||||
|
<SolidColorBrush x:Key="TextBrush" Color="{StaticResource TextColor}"/>
|
||||||
|
<SolidColorBrush x:Key="SubTextBrush" Color="{StaticResource SubTextColor}"/>
|
||||||
|
<SolidColorBrush x:Key="BorderBrush" Color="{StaticResource BorderColor}"/>
|
||||||
|
<SolidColorBrush x:Key="ErrorBrush" Color="{StaticResource ErrorColor}"/>
|
||||||
|
<SolidColorBrush x:Key="SuccessBrush" Color="{StaticResource SuccessColor}"/>
|
||||||
|
|
||||||
|
<!-- Window Background -->
|
||||||
|
<SolidColorBrush x:Key="WindowBackgroundBrush" Color="{StaticResource PrimaryColor}"/>
|
||||||
|
|
||||||
|
<!-- Button Style -->
|
||||||
|
<Style x:Key="PrimaryButtonStyle" TargetType="Button">
|
||||||
|
<Setter Property="Background" Value="{StaticResource AccentBrush}"/>
|
||||||
|
<Setter Property="Foreground" Value="White"/>
|
||||||
|
<Setter Property="BorderThickness" Value="0"/>
|
||||||
|
<Setter Property="Padding" Value="15,8"/>
|
||||||
|
<Setter Property="Cursor" Value="Hand"/>
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Border Background="{TemplateBinding Background}"
|
||||||
|
CornerRadius="4"
|
||||||
|
Padding="{TemplateBinding Padding}">
|
||||||
|
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
</Border>
|
||||||
|
<ControlTemplate.Triggers>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Setter Property="Background" Value="#1A8AD4"/>
|
||||||
|
</Trigger>
|
||||||
|
<Trigger Property="IsPressed" Value="True">
|
||||||
|
<Setter Property="Background" Value="#005A9E"/>
|
||||||
|
</Trigger>
|
||||||
|
</ControlTemplate.Triggers>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style x:Key="SecondaryButtonStyle" TargetType="Button">
|
||||||
|
<Setter Property="Background" Value="{StaticResource SecondaryBrush}"/>
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource TextBrush}"/>
|
||||||
|
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/>
|
||||||
|
<Setter Property="BorderThickness" Value="1"/>
|
||||||
|
<Setter Property="Padding" Value="15,8"/>
|
||||||
|
<Setter Property="Cursor" Value="Hand"/>
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Border Background="{TemplateBinding Background}"
|
||||||
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
CornerRadius="4"
|
||||||
|
Padding="{TemplateBinding Padding}">
|
||||||
|
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
</Border>
|
||||||
|
<ControlTemplate.Triggers>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Setter Property="Background" Value="#E0E0E0"/>
|
||||||
|
</Trigger>
|
||||||
|
</ControlTemplate.Triggers>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<!-- TextBox Style -->
|
||||||
|
<Style x:Key="DefaultTextBoxStyle" TargetType="TextBox">
|
||||||
|
<Setter Property="Background" Value="White"/>
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource TextBrush}"/>
|
||||||
|
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/>
|
||||||
|
<Setter Property="BorderThickness" Value="1"/>
|
||||||
|
<Setter Property="Padding" Value="8,6"/>
|
||||||
|
<Setter Property="CaretBrush" Value="{StaticResource TextBrush}"/>
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="TextBox">
|
||||||
|
<Border Background="{TemplateBinding Background}"
|
||||||
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
CornerRadius="4">
|
||||||
|
<ScrollViewer x:Name="PART_ContentHost" Margin="{TemplateBinding Padding}"/>
|
||||||
|
</Border>
|
||||||
|
<ControlTemplate.Triggers>
|
||||||
|
<Trigger Property="IsFocused" Value="True">
|
||||||
|
<Setter Property="BorderBrush" Value="{StaticResource AccentBrush}"/>
|
||||||
|
</Trigger>
|
||||||
|
</ControlTemplate.Triggers>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<!-- PasswordBox Style -->
|
||||||
|
<Style x:Key="DefaultPasswordBoxStyle" TargetType="PasswordBox">
|
||||||
|
<Setter Property="Background" Value="White"/>
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource TextBrush}"/>
|
||||||
|
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/>
|
||||||
|
<Setter Property="BorderThickness" Value="1"/>
|
||||||
|
<Setter Property="Padding" Value="8,6"/>
|
||||||
|
<Setter Property="CaretBrush" Value="{StaticResource TextBrush}"/>
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="PasswordBox">
|
||||||
|
<Border Background="{TemplateBinding Background}"
|
||||||
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
CornerRadius="4">
|
||||||
|
<ScrollViewer x:Name="PART_ContentHost" Margin="{TemplateBinding Padding}"/>
|
||||||
|
</Border>
|
||||||
|
<ControlTemplate.Triggers>
|
||||||
|
<Trigger Property="IsFocused" Value="True">
|
||||||
|
<Setter Property="BorderBrush" Value="{StaticResource AccentBrush}"/>
|
||||||
|
</Trigger>
|
||||||
|
</ControlTemplate.Triggers>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<!-- Label Style -->
|
||||||
|
<Style x:Key="DefaultLabelStyle" TargetType="Label">
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource TextBrush}"/>
|
||||||
|
<Setter Property="Padding" Value="0,0,0,4"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<!-- DataGrid Style -->
|
||||||
|
<Style x:Key="DefaultDataGridStyle" TargetType="DataGrid">
|
||||||
|
<Setter Property="Background" Value="White"/>
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource TextBrush}"/>
|
||||||
|
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/>
|
||||||
|
<Setter Property="BorderThickness" Value="1"/>
|
||||||
|
<Setter Property="RowBackground" Value="White"/>
|
||||||
|
<Setter Property="AlternatingRowBackground" Value="{StaticResource SecondaryBrush}"/>
|
||||||
|
<Setter Property="GridLinesVisibility" Value="Horizontal"/>
|
||||||
|
<Setter Property="HorizontalGridLinesBrush" Value="{StaticResource BorderBrush}"/>
|
||||||
|
<Setter Property="HeadersVisibility" Value="Column"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="DataGridColumnHeader">
|
||||||
|
<Setter Property="Background" Value="{StaticResource SecondaryBrush}"/>
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource TextBrush}"/>
|
||||||
|
<Setter Property="Padding" Value="10,8"/>
|
||||||
|
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/>
|
||||||
|
<Setter Property="BorderThickness" Value="0,0,1,1"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="DataGridCell">
|
||||||
|
<Setter Property="Padding" Value="10,6"/>
|
||||||
|
<Setter Property="BorderThickness" Value="0"/>
|
||||||
|
<Style.Triggers>
|
||||||
|
<Trigger Property="IsSelected" Value="True">
|
||||||
|
<Setter Property="Background" Value="{StaticResource AccentBrush}"/>
|
||||||
|
<Setter Property="Foreground" Value="White"/>
|
||||||
|
</Trigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="DataGridRow">
|
||||||
|
<Setter Property="Background" Value="Transparent"/>
|
||||||
|
<Style.Triggers>
|
||||||
|
<Trigger Property="IsSelected" Value="True">
|
||||||
|
<Setter Property="Background" Value="{StaticResource AccentBrush}"/>
|
||||||
|
</Trigger>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Setter Property="Background" Value="#E8E8E8"/>
|
||||||
|
</Trigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<!-- RadioButton Style -->
|
||||||
|
<Style x:Key="DefaultRadioButtonStyle" TargetType="RadioButton">
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource TextBrush}"/>
|
||||||
|
<Setter Property="Margin" Value="0,4"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
</ResourceDictionary>
|
||||||
61
src/WPFBeginner/Services/MemberService.cs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using WPFBeginner.Models;
|
||||||
|
|
||||||
|
namespace WPFBeginner.Services;
|
||||||
|
|
||||||
|
public interface IMemberService
|
||||||
|
{
|
||||||
|
ObservableCollection<Member> Members { get; }
|
||||||
|
void LoadDefaultMembers(List<Member> defaultMembers);
|
||||||
|
void Add(Member member);
|
||||||
|
void Remove(Member member);
|
||||||
|
void Reset();
|
||||||
|
IEnumerable<Member> Search(string keyword);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MemberService : IMemberService
|
||||||
|
{
|
||||||
|
private readonly List<Member> _defaultMembers = new();
|
||||||
|
public ObservableCollection<Member> Members { get; } = new();
|
||||||
|
|
||||||
|
public void LoadDefaultMembers(List<Member> defaultMembers)
|
||||||
|
{
|
||||||
|
_defaultMembers.Clear();
|
||||||
|
_defaultMembers.AddRange(defaultMembers.Select(m => m.Clone()));
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(Member member)
|
||||||
|
{
|
||||||
|
Members.Add(member);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Remove(Member member)
|
||||||
|
{
|
||||||
|
Members.Remove(member);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
Members.Clear();
|
||||||
|
foreach (var member in _defaultMembers)
|
||||||
|
{
|
||||||
|
Members.Add(member.Clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Member> Search(string keyword)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(keyword))
|
||||||
|
{
|
||||||
|
return Members;
|
||||||
|
}
|
||||||
|
|
||||||
|
var lowerKeyword = keyword.ToLower();
|
||||||
|
return Members.Where(m =>
|
||||||
|
m.Name.ToLower().Contains(lowerKeyword) ||
|
||||||
|
m.Call.ToLower().Contains(lowerKeyword) ||
|
||||||
|
m.EMail.ToLower().Contains(lowerKeyword) ||
|
||||||
|
m.No.ToLower().Contains(lowerKeyword));
|
||||||
|
}
|
||||||
|
}
|
||||||
114
src/WPFBeginner/Services/SettingsService.cs
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
using System.IO;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Windows;
|
||||||
|
using WPFBeginner.Models;
|
||||||
|
|
||||||
|
namespace WPFBeginner.Services;
|
||||||
|
|
||||||
|
public interface ISettingsService
|
||||||
|
{
|
||||||
|
AppSettings Settings { get; }
|
||||||
|
void Load();
|
||||||
|
void Save();
|
||||||
|
void SetLanguage(string language);
|
||||||
|
void SetTheme(string theme);
|
||||||
|
string CurrentLanguage { get; }
|
||||||
|
string CurrentTheme { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SettingsService : ISettingsService
|
||||||
|
{
|
||||||
|
private readonly string _settingsPath;
|
||||||
|
private AppSettings _settings = new();
|
||||||
|
|
||||||
|
public AppSettings Settings => _settings;
|
||||||
|
public string CurrentLanguage => _settings.Language;
|
||||||
|
public string CurrentTheme => _settings.Theme;
|
||||||
|
|
||||||
|
public SettingsService()
|
||||||
|
{
|
||||||
|
_settingsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "appsettings.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Load()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (File.Exists(_settingsPath))
|
||||||
|
{
|
||||||
|
var json = File.ReadAllText(_settingsPath);
|
||||||
|
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
|
||||||
|
_settings = JsonSerializer.Deserialize<AppSettings>(json, options) ?? new AppSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
_settings = new AppSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplyLanguage(_settings.Language);
|
||||||
|
ApplyTheme(_settings.Theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var options = new JsonSerializerOptions { WriteIndented = true };
|
||||||
|
var json = JsonSerializer.Serialize(_settings, options);
|
||||||
|
File.WriteAllText(_settingsPath, json);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignore save errors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLanguage(string language)
|
||||||
|
{
|
||||||
|
_settings.Language = language;
|
||||||
|
ApplyLanguage(language);
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetTheme(string theme)
|
||||||
|
{
|
||||||
|
_settings.Theme = theme;
|
||||||
|
ApplyTheme(theme);
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyLanguage(string language)
|
||||||
|
{
|
||||||
|
var dict = new ResourceDictionary();
|
||||||
|
var langFile = language == "en-US" ? "en-US" : "ko-KR";
|
||||||
|
dict.Source = new Uri($"pack://application:,,,/Resources/Languages/{langFile}.xaml");
|
||||||
|
|
||||||
|
// Remove existing language dictionary
|
||||||
|
var existingLang = Application.Current.Resources.MergedDictionaries
|
||||||
|
.FirstOrDefault(d => d.Source?.OriginalString.Contains("/Languages/") == true);
|
||||||
|
if (existingLang != null)
|
||||||
|
{
|
||||||
|
Application.Current.Resources.MergedDictionaries.Remove(existingLang);
|
||||||
|
}
|
||||||
|
|
||||||
|
Application.Current.Resources.MergedDictionaries.Add(dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyTheme(string theme)
|
||||||
|
{
|
||||||
|
var dict = new ResourceDictionary();
|
||||||
|
var themeFile = theme == "LightTheme" ? "LightTheme" : "DefaultTheme";
|
||||||
|
dict.Source = new Uri($"pack://application:,,,/Resources/Themes/{themeFile}.xaml");
|
||||||
|
|
||||||
|
// Remove existing theme dictionary
|
||||||
|
var existingTheme = Application.Current.Resources.MergedDictionaries
|
||||||
|
.FirstOrDefault(d => d.Source?.OriginalString.Contains("/Themes/") == true);
|
||||||
|
if (existingTheme != null)
|
||||||
|
{
|
||||||
|
Application.Current.Resources.MergedDictionaries.Remove(existingTheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
Application.Current.Resources.MergedDictionaries.Add(dict);
|
||||||
|
}
|
||||||
|
}
|
||||||
62
src/WPFBeginner/ViewModels/LoginViewModel.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
using System.Windows;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
using WPFBeginner.Services;
|
||||||
|
using WPFBeginner.Views;
|
||||||
|
|
||||||
|
namespace WPFBeginner.ViewModels;
|
||||||
|
|
||||||
|
public partial class LoginViewModel : ObservableObject
|
||||||
|
{
|
||||||
|
private readonly ISettingsService _settingsService;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _userId = string.Empty;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _password = string.Empty;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _errorMessage = string.Empty;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool _hasError;
|
||||||
|
|
||||||
|
public string WelcomeMessage => _settingsService.CurrentLanguage == "en-US"
|
||||||
|
? "Welcome"
|
||||||
|
: "환영합니다";
|
||||||
|
|
||||||
|
public LoginViewModel(ISettingsService settingsService)
|
||||||
|
{
|
||||||
|
_settingsService = settingsService;
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void Login(Window window)
|
||||||
|
{
|
||||||
|
var settings = _settingsService.Settings.Login;
|
||||||
|
|
||||||
|
if (UserId == settings.User && Password == settings.Password)
|
||||||
|
{
|
||||||
|
HasError = false;
|
||||||
|
ErrorMessage = string.Empty;
|
||||||
|
|
||||||
|
var mainWindow = new MainWindow();
|
||||||
|
mainWindow.Show();
|
||||||
|
window.Close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HasError = true;
|
||||||
|
ErrorMessage = _settingsService.CurrentLanguage == "en-US"
|
||||||
|
? "Invalid ID or Password"
|
||||||
|
: "아이디 또는 비밀번호가 틀렸습니다";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void Close(Window window)
|
||||||
|
{
|
||||||
|
Application.Current.Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
165
src/WPFBeginner/ViewModels/MainViewModel.cs
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Windows;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
using WPFBeginner.Models;
|
||||||
|
using WPFBeginner.Services;
|
||||||
|
using WPFBeginner.Views;
|
||||||
|
|
||||||
|
namespace WPFBeginner.ViewModels;
|
||||||
|
|
||||||
|
public partial class MainViewModel : ObservableObject
|
||||||
|
{
|
||||||
|
private readonly ISettingsService _settingsService;
|
||||||
|
private readonly IMemberService _memberService;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _searchKeyword = string.Empty;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private Member? _selectedMember;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private ObservableCollection<Member> _filteredMembers = new();
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool _isKorean = true;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool _isEnglish;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool _isDefaultTheme = true;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool _isLightTheme;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _searchResultMessage = string.Empty;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool _hasSearchResult = true;
|
||||||
|
|
||||||
|
public MainViewModel(ISettingsService settingsService, IMemberService memberService)
|
||||||
|
{
|
||||||
|
_settingsService = settingsService;
|
||||||
|
_memberService = memberService;
|
||||||
|
|
||||||
|
// Load default members
|
||||||
|
_memberService.LoadDefaultMembers(_settingsService.Settings.DefaultMembers);
|
||||||
|
|
||||||
|
// Set initial language/theme based on settings
|
||||||
|
IsKorean = _settingsService.CurrentLanguage == "ko-KR";
|
||||||
|
IsEnglish = _settingsService.CurrentLanguage == "en-US";
|
||||||
|
IsDefaultTheme = _settingsService.CurrentTheme == "DefaultTheme";
|
||||||
|
IsLightTheme = _settingsService.CurrentTheme == "LightTheme";
|
||||||
|
|
||||||
|
// Initialize filtered members
|
||||||
|
RefreshFilteredMembers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshFilteredMembers()
|
||||||
|
{
|
||||||
|
FilteredMembers = new ObservableCollection<Member>(_memberService.Members);
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void Search()
|
||||||
|
{
|
||||||
|
var results = _memberService.Search(SearchKeyword).ToList();
|
||||||
|
FilteredMembers = new ObservableCollection<Member>(results);
|
||||||
|
|
||||||
|
if (results.Count == 0)
|
||||||
|
{
|
||||||
|
HasSearchResult = false;
|
||||||
|
SearchResultMessage = _settingsService.CurrentLanguage == "en-US"
|
||||||
|
? "No results found"
|
||||||
|
: "검색 결과가 없습니다";
|
||||||
|
|
||||||
|
MessageBox.Show(SearchResultMessage,
|
||||||
|
_settingsService.CurrentLanguage == "en-US" ? "Search" : "검색",
|
||||||
|
MessageBoxButton.OK,
|
||||||
|
MessageBoxImage.Information);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HasSearchResult = true;
|
||||||
|
SearchResultMessage = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void AddMember()
|
||||||
|
{
|
||||||
|
var registWindow = new RegistWindow();
|
||||||
|
registWindow.MemberAdded += OnMemberAdded;
|
||||||
|
registWindow.ShowDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMemberAdded(object? sender, Member member)
|
||||||
|
{
|
||||||
|
_memberService.Add(member);
|
||||||
|
RefreshFilteredMembers();
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void DeleteMember()
|
||||||
|
{
|
||||||
|
if (SelectedMember != null)
|
||||||
|
{
|
||||||
|
_memberService.Remove(SelectedMember);
|
||||||
|
RefreshFilteredMembers();
|
||||||
|
SelectedMember = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void Reset()
|
||||||
|
{
|
||||||
|
SearchKeyword = string.Empty;
|
||||||
|
_memberService.Reset();
|
||||||
|
RefreshFilteredMembers();
|
||||||
|
HasSearchResult = true;
|
||||||
|
SearchResultMessage = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void SetKorean()
|
||||||
|
{
|
||||||
|
IsKorean = true;
|
||||||
|
IsEnglish = false;
|
||||||
|
_settingsService.SetLanguage("ko-KR");
|
||||||
|
OnPropertyChanged(nameof(IsKorean));
|
||||||
|
OnPropertyChanged(nameof(IsEnglish));
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void SetEnglish()
|
||||||
|
{
|
||||||
|
IsKorean = false;
|
||||||
|
IsEnglish = true;
|
||||||
|
_settingsService.SetLanguage("en-US");
|
||||||
|
OnPropertyChanged(nameof(IsKorean));
|
||||||
|
OnPropertyChanged(nameof(IsEnglish));
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void SetDefaultTheme()
|
||||||
|
{
|
||||||
|
IsDefaultTheme = true;
|
||||||
|
IsLightTheme = false;
|
||||||
|
_settingsService.SetTheme("DefaultTheme");
|
||||||
|
OnPropertyChanged(nameof(IsDefaultTheme));
|
||||||
|
OnPropertyChanged(nameof(IsLightTheme));
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void SetLightTheme()
|
||||||
|
{
|
||||||
|
IsDefaultTheme = false;
|
||||||
|
IsLightTheme = true;
|
||||||
|
_settingsService.SetTheme("LightTheme");
|
||||||
|
OnPropertyChanged(nameof(IsDefaultTheme));
|
||||||
|
OnPropertyChanged(nameof(IsLightTheme));
|
||||||
|
}
|
||||||
|
}
|
||||||
93
src/WPFBeginner/ViewModels/RegistViewModel.cs
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
using System.Windows;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
using WPFBeginner.Models;
|
||||||
|
using WPFBeginner.Services;
|
||||||
|
|
||||||
|
namespace WPFBeginner.ViewModels;
|
||||||
|
|
||||||
|
public partial class RegistViewModel : ObservableObject
|
||||||
|
{
|
||||||
|
private readonly ISettingsService _settingsService;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _name = string.Empty;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _call = string.Empty;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _eMail = string.Empty;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _no = string.Empty;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _errorMessage = string.Empty;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool _hasError;
|
||||||
|
|
||||||
|
public event EventHandler<Member>? MemberAdded;
|
||||||
|
|
||||||
|
public RegistViewModel(ISettingsService settingsService)
|
||||||
|
{
|
||||||
|
_settingsService = settingsService;
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void Register(Window window)
|
||||||
|
{
|
||||||
|
// Validate required fields
|
||||||
|
if (string.IsNullOrWhiteSpace(Name))
|
||||||
|
{
|
||||||
|
HasError = true;
|
||||||
|
ErrorMessage = _settingsService.CurrentLanguage == "en-US"
|
||||||
|
? "Name is required"
|
||||||
|
: "이름은 필수입니다";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(EMail))
|
||||||
|
{
|
||||||
|
HasError = true;
|
||||||
|
ErrorMessage = _settingsService.CurrentLanguage == "en-US"
|
||||||
|
? "Email is required"
|
||||||
|
: "이메일은 필수입니다";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HasError = false;
|
||||||
|
ErrorMessage = string.Empty;
|
||||||
|
|
||||||
|
var member = new Member(Name, Call, EMail, No);
|
||||||
|
MemberAdded?.Invoke(this, member);
|
||||||
|
window.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void Cancel(Window window)
|
||||||
|
{
|
||||||
|
window.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void Minimize(Window window)
|
||||||
|
{
|
||||||
|
window.WindowState = WindowState.Minimized;
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void Maximize(Window window)
|
||||||
|
{
|
||||||
|
window.WindowState = window.WindowState == WindowState.Maximized
|
||||||
|
? WindowState.Normal
|
||||||
|
: WindowState.Maximized;
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void Close(Window window)
|
||||||
|
{
|
||||||
|
window.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
198
src/WPFBeginner/Views/LoginWindow.xaml
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
<Window x:Class="WPFBeginner.Views.LoginWindow"
|
||||||
|
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"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
Title="{DynamicResource Login_Title}"
|
||||||
|
Height="540" Width="440"
|
||||||
|
WindowStartupLocation="CenterScreen"
|
||||||
|
WindowStyle="None"
|
||||||
|
AllowsTransparency="True"
|
||||||
|
Background="Transparent"
|
||||||
|
ResizeMode="NoResize">
|
||||||
|
|
||||||
|
<Border Margin="15" CornerRadius="12">
|
||||||
|
<Border.Effect>
|
||||||
|
<DropShadowEffect BlurRadius="15" ShadowDepth="0" Opacity="0.5"/>
|
||||||
|
</Border.Effect>
|
||||||
|
<Border.Background>
|
||||||
|
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
|
||||||
|
<GradientStop Color="#1a1a2e" Offset="0"/>
|
||||||
|
<GradientStop Color="#16213e" Offset="1"/>
|
||||||
|
</LinearGradientBrush>
|
||||||
|
</Border.Background>
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<!-- Title Bar -->
|
||||||
|
<Grid Grid.Row="0" Background="Transparent" MouseLeftButtonDown="TitleBar_MouseLeftButtonDown">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<Button Grid.Column="1"
|
||||||
|
Content="✕"
|
||||||
|
Width="45" Height="35"
|
||||||
|
Background="Transparent"
|
||||||
|
Foreground="#808080"
|
||||||
|
BorderThickness="0"
|
||||||
|
FontSize="14"
|
||||||
|
Cursor="Hand"
|
||||||
|
Command="{Binding CloseCommand}"
|
||||||
|
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}">
|
||||||
|
<Button.Style>
|
||||||
|
<Style TargetType="Button">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Border Background="{TemplateBinding Background}" CornerRadius="0,12,0,0">
|
||||||
|
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
</Border>
|
||||||
|
<ControlTemplate.Triggers>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Setter Property="Background" Value="#E81123"/>
|
||||||
|
<Setter Property="Foreground" Value="White"/>
|
||||||
|
</Trigger>
|
||||||
|
</ControlTemplate.Triggers>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</Button.Style>
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Content -->
|
||||||
|
<StackPanel Grid.Row="1" Margin="40,10,40,30" VerticalAlignment="Center">
|
||||||
|
|
||||||
|
<!-- Logo Icon -->
|
||||||
|
<Border Width="70" Height="70"
|
||||||
|
CornerRadius="35"
|
||||||
|
Margin="0,0,0,20"
|
||||||
|
HorizontalAlignment="Center">
|
||||||
|
<Border.Background>
|
||||||
|
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
|
||||||
|
<GradientStop Color="#0f3460" Offset="0"/>
|
||||||
|
<GradientStop Color="#e94560" Offset="1"/>
|
||||||
|
</LinearGradientBrush>
|
||||||
|
</Border.Background>
|
||||||
|
<TextBlock Text="W"
|
||||||
|
FontSize="32"
|
||||||
|
FontWeight="Bold"
|
||||||
|
Foreground="White"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center"/>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<!-- Welcome Message -->
|
||||||
|
<TextBlock Text="{DynamicResource Login_Welcome}"
|
||||||
|
Foreground="White"
|
||||||
|
FontSize="26"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
Margin="0,0,0,5"/>
|
||||||
|
|
||||||
|
<TextBlock Text="WPF Beginner"
|
||||||
|
Foreground="#808080"
|
||||||
|
FontSize="13"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
Margin="0,0,0,25"/>
|
||||||
|
|
||||||
|
<!-- User ID -->
|
||||||
|
<TextBlock Text="{DynamicResource Login_UserId}"
|
||||||
|
Foreground="#a0a0a0"
|
||||||
|
FontSize="12"
|
||||||
|
Margin="5,0,0,6"/>
|
||||||
|
<Border CornerRadius="8" Background="#0f3460" Margin="0,0,0,15">
|
||||||
|
<TextBox Text="{Binding UserId, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
Background="Transparent"
|
||||||
|
Foreground="White"
|
||||||
|
BorderThickness="0"
|
||||||
|
Padding="12,10"
|
||||||
|
FontSize="14"
|
||||||
|
CaretBrush="White"/>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<!-- Password -->
|
||||||
|
<TextBlock Text="{DynamicResource Login_Password}"
|
||||||
|
Foreground="#a0a0a0"
|
||||||
|
FontSize="12"
|
||||||
|
Margin="5,0,0,6"/>
|
||||||
|
<Border CornerRadius="8" Background="#0f3460" Margin="0,0,0,12">
|
||||||
|
<PasswordBox x:Name="PasswordBox"
|
||||||
|
Background="Transparent"
|
||||||
|
Foreground="White"
|
||||||
|
BorderThickness="0"
|
||||||
|
Padding="12,10"
|
||||||
|
FontSize="14"
|
||||||
|
CaretBrush="White"
|
||||||
|
PasswordChanged="PasswordBox_PasswordChanged"/>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<!-- Error Message -->
|
||||||
|
<Border Background="#3d1f2f"
|
||||||
|
CornerRadius="6"
|
||||||
|
Padding="10,6"
|
||||||
|
Margin="0,0,0,10"
|
||||||
|
Visibility="{Binding HasError, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||||
|
<TextBlock Text="{Binding ErrorMessage}"
|
||||||
|
Foreground="#ff6b6b"
|
||||||
|
FontSize="12"
|
||||||
|
HorizontalAlignment="Center"/>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<!-- Login Button -->
|
||||||
|
<Button Command="{Binding LoginCommand}"
|
||||||
|
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
|
||||||
|
Cursor="Hand"
|
||||||
|
Margin="0,5,0,0">
|
||||||
|
<Button.Template>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Border x:Name="ButtonBorder" CornerRadius="8" Padding="15,12">
|
||||||
|
<Border.Background>
|
||||||
|
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
|
||||||
|
<GradientStop Color="#e94560" Offset="0"/>
|
||||||
|
<GradientStop Color="#0f3460" Offset="1"/>
|
||||||
|
</LinearGradientBrush>
|
||||||
|
</Border.Background>
|
||||||
|
<TextBlock Text="{DynamicResource Login_LoginButton}"
|
||||||
|
Foreground="White"
|
||||||
|
FontSize="15"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
HorizontalAlignment="Center"/>
|
||||||
|
</Border>
|
||||||
|
<ControlTemplate.Triggers>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Setter TargetName="ButtonBorder" Property="Background">
|
||||||
|
<Setter.Value>
|
||||||
|
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
|
||||||
|
<GradientStop Color="#ff6b6b" Offset="0"/>
|
||||||
|
<GradientStop Color="#1a5276" Offset="1"/>
|
||||||
|
</LinearGradientBrush>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Trigger>
|
||||||
|
<Trigger Property="IsPressed" Value="True">
|
||||||
|
<Setter TargetName="ButtonBorder" Property="Background">
|
||||||
|
<Setter.Value>
|
||||||
|
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
|
||||||
|
<GradientStop Color="#c0392b" Offset="0"/>
|
||||||
|
<GradientStop Color="#0a3d62" Offset="1"/>
|
||||||
|
</LinearGradientBrush>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Trigger>
|
||||||
|
</ControlTemplate.Triggers>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Button.Template>
|
||||||
|
</Button>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</Window>
|
||||||
30
src/WPFBeginner/Views/LoginWindow.xaml.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using WPFBeginner.ViewModels;
|
||||||
|
|
||||||
|
namespace WPFBeginner.Views;
|
||||||
|
|
||||||
|
public partial class LoginWindow : Window
|
||||||
|
{
|
||||||
|
public LoginWindow()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
DataContext = App.GetService<LoginViewModel>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.ClickCount == 1)
|
||||||
|
{
|
||||||
|
DragMove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (DataContext is LoginViewModel viewModel)
|
||||||
|
{
|
||||||
|
viewModel.Password = PasswordBox.Password;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
143
src/WPFBeginner/Views/MainWindow.xaml
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
<Window x:Class="WPFBeginner.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
Title="{DynamicResource Main_Title}"
|
||||||
|
Height="600" Width="900"
|
||||||
|
MinWidth="700" MinHeight="400"
|
||||||
|
WindowStartupLocation="CenterScreen"
|
||||||
|
Background="{DynamicResource WindowBackgroundBrush}">
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<!-- Top Bar -->
|
||||||
|
<Border Grid.Row="0" Background="{DynamicResource SecondaryBrush}" Padding="15,10">
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<!-- Search Area -->
|
||||||
|
<StackPanel Grid.Column="0" Orientation="Horizontal">
|
||||||
|
<TextBox Text="{Binding SearchKeyword, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
Style="{DynamicResource DefaultTextBoxStyle}"
|
||||||
|
Width="250"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
KeyDown="SearchTextBox_KeyDown"/>
|
||||||
|
<Button Content="{DynamicResource Main_Search}"
|
||||||
|
Style="{DynamicResource PrimaryButtonStyle}"
|
||||||
|
Command="{Binding SearchCommand}"
|
||||||
|
Margin="10,0,0,0"
|
||||||
|
Padding="20,8"/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Action Buttons -->
|
||||||
|
<StackPanel Grid.Column="1" Orientation="Horizontal">
|
||||||
|
<Button Content="{DynamicResource Main_Add}"
|
||||||
|
Style="{DynamicResource PrimaryButtonStyle}"
|
||||||
|
Command="{Binding AddMemberCommand}"
|
||||||
|
Margin="0,0,10,0"/>
|
||||||
|
<Button Content="{DynamicResource Main_Delete}"
|
||||||
|
Style="{DynamicResource SecondaryButtonStyle}"
|
||||||
|
Command="{Binding DeleteMemberCommand}"
|
||||||
|
Margin="0,0,10,0"/>
|
||||||
|
<Button Content="{DynamicResource Main_Reset}"
|
||||||
|
Style="{DynamicResource SecondaryButtonStyle}"
|
||||||
|
Command="{Binding ResetCommand}"
|
||||||
|
Margin="0,0,10,0"/>
|
||||||
|
<Button x:Name="SettingsButton"
|
||||||
|
Content="{DynamicResource Main_Settings}"
|
||||||
|
Style="{DynamicResource SecondaryButtonStyle}"
|
||||||
|
Click="SettingsButton_Click"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<!-- Main Content -->
|
||||||
|
<Grid Grid.Row="1">
|
||||||
|
<!-- DataGrid -->
|
||||||
|
<DataGrid ItemsSource="{Binding FilteredMembers}"
|
||||||
|
SelectedItem="{Binding SelectedMember}"
|
||||||
|
Style="{DynamicResource DefaultDataGridStyle}"
|
||||||
|
AutoGenerateColumns="False"
|
||||||
|
IsReadOnly="True"
|
||||||
|
SelectionMode="Single"
|
||||||
|
Margin="15">
|
||||||
|
<DataGrid.Columns>
|
||||||
|
<DataGridTextColumn Header="{DynamicResource Main_Column_Name}"
|
||||||
|
Binding="{Binding Name}"
|
||||||
|
Width="*"/>
|
||||||
|
<DataGridTextColumn Header="{DynamicResource Main_Column_Call}"
|
||||||
|
Binding="{Binding Call}"
|
||||||
|
Width="*"/>
|
||||||
|
<DataGridTextColumn Header="{DynamicResource Main_Column_Email}"
|
||||||
|
Binding="{Binding EMail}"
|
||||||
|
Width="2*"/>
|
||||||
|
<DataGridTextColumn Header="{DynamicResource Main_Column_No}"
|
||||||
|
Binding="{Binding No}"
|
||||||
|
Width="*"/>
|
||||||
|
</DataGrid.Columns>
|
||||||
|
</DataGrid>
|
||||||
|
|
||||||
|
<!-- Settings Panel (Popup) -->
|
||||||
|
<Popup x:Name="SettingsPopup"
|
||||||
|
Placement="Bottom"
|
||||||
|
PlacementTarget="{Binding ElementName=SettingsButton}"
|
||||||
|
StaysOpen="False"
|
||||||
|
AllowsTransparency="True">
|
||||||
|
<Border Background="{DynamicResource SecondaryBrush}"
|
||||||
|
BorderBrush="{DynamicResource BorderBrush}"
|
||||||
|
BorderThickness="1"
|
||||||
|
CornerRadius="4"
|
||||||
|
Padding="15"
|
||||||
|
Margin="5">
|
||||||
|
<Border.Effect>
|
||||||
|
<DropShadowEffect BlurRadius="10" Opacity="0.3"/>
|
||||||
|
</Border.Effect>
|
||||||
|
<StackPanel Width="200">
|
||||||
|
<!-- Language Settings -->
|
||||||
|
<TextBlock Text="{DynamicResource Settings_Language}"
|
||||||
|
Foreground="{DynamicResource TextBrush}"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Margin="0,0,0,10"/>
|
||||||
|
<RadioButton Content="{DynamicResource Settings_Korean}"
|
||||||
|
IsChecked="{Binding IsKorean}"
|
||||||
|
Style="{DynamicResource DefaultRadioButtonStyle}"
|
||||||
|
GroupName="Language"
|
||||||
|
Command="{Binding SetKoreanCommand}"/>
|
||||||
|
<RadioButton Content="{DynamicResource Settings_English}"
|
||||||
|
IsChecked="{Binding IsEnglish}"
|
||||||
|
Style="{DynamicResource DefaultRadioButtonStyle}"
|
||||||
|
GroupName="Language"
|
||||||
|
Command="{Binding SetEnglishCommand}"/>
|
||||||
|
|
||||||
|
<Separator Margin="0,15" Background="{DynamicResource BorderBrush}"/>
|
||||||
|
|
||||||
|
<!-- Theme Settings -->
|
||||||
|
<TextBlock Text="{DynamicResource Settings_Theme}"
|
||||||
|
Foreground="{DynamicResource TextBrush}"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Margin="0,0,0,10"/>
|
||||||
|
<RadioButton Content="{DynamicResource Settings_DefaultTheme}"
|
||||||
|
IsChecked="{Binding IsDefaultTheme}"
|
||||||
|
Style="{DynamicResource DefaultRadioButtonStyle}"
|
||||||
|
GroupName="Theme"
|
||||||
|
Command="{Binding SetDefaultThemeCommand}"/>
|
||||||
|
<RadioButton Content="{DynamicResource Settings_LightTheme}"
|
||||||
|
IsChecked="{Binding IsLightTheme}"
|
||||||
|
Style="{DynamicResource DefaultRadioButtonStyle}"
|
||||||
|
GroupName="Theme"
|
||||||
|
Command="{Binding SetLightThemeCommand}"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</Popup>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Window>
|
||||||
27
src/WPFBeginner/Views/MainWindow.xaml.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using WPFBeginner.ViewModels;
|
||||||
|
|
||||||
|
namespace WPFBeginner.Views;
|
||||||
|
|
||||||
|
public partial class MainWindow : Window
|
||||||
|
{
|
||||||
|
public MainWindow()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
DataContext = App.GetService<MainViewModel>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SettingsButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
SettingsPopup.IsOpen = !SettingsPopup.IsOpen;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SearchTextBox_KeyDown(object sender, KeyEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Key == Key.Enter && DataContext is MainViewModel viewModel)
|
||||||
|
{
|
||||||
|
viewModel.SearchCommand.Execute(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
183
src/WPFBeginner/Views/RegistWindow.xaml
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
<Window x:Class="WPFBeginner.Views.RegistWindow"
|
||||||
|
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:controls="clr-namespace:WPFBeginner.Controls"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
Title="{DynamicResource Regist_Title}"
|
||||||
|
Height="450" Width="400"
|
||||||
|
WindowStartupLocation="CenterScreen"
|
||||||
|
WindowStyle="None"
|
||||||
|
AllowsTransparency="True"
|
||||||
|
Background="Transparent"
|
||||||
|
ResizeMode="CanResize">
|
||||||
|
|
||||||
|
<Border Background="{DynamicResource WindowBackgroundBrush}"
|
||||||
|
CornerRadius="8"
|
||||||
|
BorderBrush="{DynamicResource BorderBrush}"
|
||||||
|
BorderThickness="1">
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<!-- Custom Title Bar -->
|
||||||
|
<Grid Grid.Row="0" Background="{DynamicResource SecondaryBrush}" MouseLeftButtonDown="TitleBar_MouseLeftButtonDown">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<TextBlock Text="{DynamicResource Regist_Title}"
|
||||||
|
Foreground="{DynamicResource TextBrush}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Margin="15,10"
|
||||||
|
FontSize="14"
|
||||||
|
FontWeight="SemiBold"/>
|
||||||
|
|
||||||
|
<!-- Minimize Button -->
|
||||||
|
<Button Grid.Column="1"
|
||||||
|
Content="─"
|
||||||
|
Width="40" Height="35"
|
||||||
|
Background="Transparent"
|
||||||
|
Foreground="{DynamicResource TextBrush}"
|
||||||
|
BorderThickness="0"
|
||||||
|
FontSize="12"
|
||||||
|
Command="{Binding MinimizeCommand}"
|
||||||
|
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}">
|
||||||
|
<Button.Style>
|
||||||
|
<Style TargetType="Button">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Border Background="{TemplateBinding Background}">
|
||||||
|
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
</Border>
|
||||||
|
<ControlTemplate.Triggers>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Setter Property="Background" Value="#4E4E52"/>
|
||||||
|
</Trigger>
|
||||||
|
</ControlTemplate.Triggers>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</Button.Style>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<!-- Maximize Button -->
|
||||||
|
<Button Grid.Column="2"
|
||||||
|
Content="☐"
|
||||||
|
Width="40" Height="35"
|
||||||
|
Background="Transparent"
|
||||||
|
Foreground="{DynamicResource TextBrush}"
|
||||||
|
BorderThickness="0"
|
||||||
|
FontSize="12"
|
||||||
|
Command="{Binding MaximizeCommand}"
|
||||||
|
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}">
|
||||||
|
<Button.Style>
|
||||||
|
<Style TargetType="Button">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Border Background="{TemplateBinding Background}">
|
||||||
|
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
</Border>
|
||||||
|
<ControlTemplate.Triggers>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Setter Property="Background" Value="#4E4E52"/>
|
||||||
|
</Trigger>
|
||||||
|
</ControlTemplate.Triggers>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</Button.Style>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<!-- Close Button -->
|
||||||
|
<Button Grid.Column="3"
|
||||||
|
Content="✕"
|
||||||
|
Width="40" Height="35"
|
||||||
|
Background="Transparent"
|
||||||
|
Foreground="{DynamicResource TextBrush}"
|
||||||
|
BorderThickness="0"
|
||||||
|
FontSize="14"
|
||||||
|
Command="{Binding CloseCommand}"
|
||||||
|
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}">
|
||||||
|
<Button.Style>
|
||||||
|
<Style TargetType="Button">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Border Background="{TemplateBinding Background}">
|
||||||
|
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
</Border>
|
||||||
|
<ControlTemplate.Triggers>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Setter Property="Background" Value="#E81123"/>
|
||||||
|
</Trigger>
|
||||||
|
</ControlTemplate.Triggers>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</Button.Style>
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Content -->
|
||||||
|
<StackPanel Grid.Row="1" Margin="25,20">
|
||||||
|
<!-- Name Input -->
|
||||||
|
<controls:InputPanel LabelText="{DynamicResource Regist_Name}"
|
||||||
|
Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
IsRequired="True"
|
||||||
|
Margin="0,0,0,15"/>
|
||||||
|
|
||||||
|
<!-- Phone Input -->
|
||||||
|
<controls:InputPanel LabelText="{DynamicResource Regist_Call}"
|
||||||
|
Text="{Binding Call, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
Margin="0,0,0,15"/>
|
||||||
|
|
||||||
|
<!-- Email Input -->
|
||||||
|
<controls:InputPanel LabelText="{DynamicResource Regist_Email}"
|
||||||
|
Text="{Binding EMail, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
IsRequired="True"
|
||||||
|
Margin="0,0,0,15"/>
|
||||||
|
|
||||||
|
<!-- Employee No Input -->
|
||||||
|
<controls:InputPanel LabelText="{DynamicResource Regist_No}"
|
||||||
|
Text="{Binding No, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
Margin="0,0,0,10"/>
|
||||||
|
|
||||||
|
<!-- Error Message -->
|
||||||
|
<TextBlock Text="{Binding ErrorMessage}"
|
||||||
|
Foreground="{DynamicResource ErrorBrush}"
|
||||||
|
Visibility="{Binding HasError, Converter={StaticResource BoolToVisibilityConverter}}"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
Margin="0,10,0,0"
|
||||||
|
FontSize="12"/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Buttons -->
|
||||||
|
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right" Margin="25,0,25,20">
|
||||||
|
<Button Content="{DynamicResource Regist_Cancel}"
|
||||||
|
Style="{DynamicResource SecondaryButtonStyle}"
|
||||||
|
Command="{Binding CancelCommand}"
|
||||||
|
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
|
||||||
|
Width="80"
|
||||||
|
Margin="0,0,10,0"/>
|
||||||
|
<Button Content="{DynamicResource Regist_Register}"
|
||||||
|
Style="{DynamicResource PrimaryButtonStyle}"
|
||||||
|
Command="{Binding RegisterCommand}"
|
||||||
|
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
|
||||||
|
Width="80"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</Window>
|
||||||
32
src/WPFBeginner/Views/RegistWindow.xaml.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using WPFBeginner.Models;
|
||||||
|
using WPFBeginner.ViewModels;
|
||||||
|
|
||||||
|
namespace WPFBeginner.Views;
|
||||||
|
|
||||||
|
public partial class RegistWindow : Window
|
||||||
|
{
|
||||||
|
public event EventHandler<Member>? MemberAdded;
|
||||||
|
|
||||||
|
public RegistWindow()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
var viewModel = App.GetService<RegistViewModel>();
|
||||||
|
viewModel.MemberAdded += OnMemberAdded;
|
||||||
|
DataContext = viewModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMemberAdded(object? sender, Member member)
|
||||||
|
{
|
||||||
|
MemberAdded?.Invoke(this, member);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.ClickCount == 1)
|
||||||
|
{
|
||||||
|
DragMove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/WPFBeginner/WPFBeginner.csproj
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<TargetFramework>net8.0-windows</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<UseWPF>true</UseWPF>
|
||||||
|
<ApplicationIcon></ApplicationIcon>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="appsettings.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
<Application x:Class="WPFBeginner.App"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:service="clr-namespace:WPFBeginner.Services"
|
|
||||||
xmlns:conv="clr-namespace:WPFBeginner.Converters"
|
|
||||||
Startup="Application_Startup">
|
|
||||||
<Application.Resources>
|
|
||||||
<ResourceDictionary>
|
|
||||||
<service:ViewModelLocator x:Key="ViewModelLocator"/>
|
|
||||||
<conv:InverseBoolConverter x:Key="InverseBoolConverter"/>
|
|
||||||
|
|
||||||
<ResourceDictionary.MergedDictionaries>
|
|
||||||
<ResourceDictionary Source="pack://application:,,,/Themes/Styles/Buttons.xaml" />
|
|
||||||
<ResourceDictionary Source="pack://application:,,,/Themes/Colors/DefaultTheme.xaml" />
|
|
||||||
<ResourceDictionary Source="pack://application:,,,/Themes/Cultures/ko-KR.xaml" />
|
|
||||||
<ResourceDictionary Source="pack://application:,,,/Resources/Images/DrawingImages.xaml" />
|
|
||||||
</ResourceDictionary.MergedDictionaries>
|
|
||||||
</ResourceDictionary>
|
|
||||||
</Application.Resources>
|
|
||||||
</Application>
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text.Json;
|
|
||||||
using System.Windows;
|
|
||||||
using WPFBeginner.Configurations;
|
|
||||||
using WPFBeginner.Exceptions;
|
|
||||||
using WPFBeginner.Services;
|
|
||||||
using WPFBeginner.ViewModels;
|
|
||||||
using WPFBeginner.Views;
|
|
||||||
|
|
||||||
namespace WPFBeginner
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Interaction logic for App.xaml
|
|
||||||
/// </summary>
|
|
||||||
public partial class App : Application
|
|
||||||
{
|
|
||||||
private readonly static Dictionary<string, ResourceDictionary> _languages = new Dictionary<string, ResourceDictionary>();
|
|
||||||
private static ResourceDictionary _currentLanguage;
|
|
||||||
|
|
||||||
private readonly static Dictionary<string, ResourceDictionary> _themes = new Dictionary<string, ResourceDictionary>();
|
|
||||||
private static ResourceDictionary _currentTheme;
|
|
||||||
|
|
||||||
public static AppSettings Config { get; private set; }
|
|
||||||
|
|
||||||
private void Application_Startup(object sender, StartupEventArgs e)
|
|
||||||
{
|
|
||||||
InitializeService();
|
|
||||||
var main = new MainWindow();
|
|
||||||
App.Current.MainWindow = main;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Login();
|
|
||||||
|
|
||||||
Application.Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
|
|
||||||
App.Current.MainWindow.Show();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
App.Current.MainWindow.Close();
|
|
||||||
Environment.Exit(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UnhandledExceptionHandle(object e)
|
|
||||||
{
|
|
||||||
if (e is UnhandledExceptionEventArgs uee && uee.ExceptionObject is LoginFailedException)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void InitializeService()
|
|
||||||
{
|
|
||||||
Config = JsonSerializer.Deserialize<AppSettings>(File.ReadAllText("appsettings.json"));
|
|
||||||
|
|
||||||
_languages.Add("ko-KR", ResourceExplorer.GetLanguageResourceDic("ko-KR"));
|
|
||||||
_languages.Add("en-US", ResourceExplorer.GetLanguageResourceDic("en-US"));
|
|
||||||
SetLanguage(Config.Language);
|
|
||||||
|
|
||||||
_themes.Add("DefaultTheme", ResourceExplorer.GetThemeResourceDic("DefaultTheme"));
|
|
||||||
_themes.Add("LightTheme", ResourceExplorer.GetThemeResourceDic("LightTheme"));
|
|
||||||
SetTheme(Config.Theme);
|
|
||||||
|
|
||||||
Config.LanguageChanged += (s, e) => SetLanguage(e.New);
|
|
||||||
Config.ThemeChanged += (s, e) => SetTheme(e.New);
|
|
||||||
|
|
||||||
Ioc.Default.ConfigureServices(
|
|
||||||
new ServiceCollection()
|
|
||||||
.AddSingleton(new MainWindowViewModel())
|
|
||||||
.BuildServiceProvider());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void SetTheme(string code)
|
|
||||||
{
|
|
||||||
if (_currentTheme != null)
|
|
||||||
App.Current.Resources.MergedDictionaries.Remove(_currentTheme);
|
|
||||||
|
|
||||||
_currentTheme = ResourceExplorer.GetThemeResourceDic(code);
|
|
||||||
App.Current.Resources.MergedDictionaries.Add(_currentTheme);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void SetLanguage(string code)
|
|
||||||
{
|
|
||||||
if (_currentLanguage != null)
|
|
||||||
App.Current.Resources.MergedDictionaries.Remove(_currentLanguage);
|
|
||||||
|
|
||||||
_currentLanguage = ResourceExplorer.GetLanguageResourceDic(code);
|
|
||||||
App.Current.Resources.MergedDictionaries.Add(_currentLanguage);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void Login()
|
|
||||||
{
|
|
||||||
var login = new LoginWindow();
|
|
||||||
var isSuccess = login.ShowDialog();
|
|
||||||
|
|
||||||
if (isSuccess != true)
|
|
||||||
throw new LoginFailedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,279 +0,0 @@
|
|||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Interop;
|
|
||||||
|
|
||||||
namespace WPFBeginner.Behaviors
|
|
||||||
{
|
|
||||||
public class WindowBehavior
|
|
||||||
{
|
|
||||||
#region Win32 imports
|
|
||||||
|
|
||||||
private const int GWL_STYLE = -16;
|
|
||||||
private const int WS_SYSMENU = 0x80000;
|
|
||||||
private const int WS_MAXIMIZEBOX = 0x80000;
|
|
||||||
private const int WS_MINIMIZEBOX = 0x80000;
|
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true)]
|
|
||||||
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private static readonly Type OwnerType = typeof(WindowBehavior);
|
|
||||||
|
|
||||||
#region HideCloseButton (attached property)
|
|
||||||
|
|
||||||
private static readonly RoutedEventHandler HideCloseButtonWhenLoadedDelegate = (sender, args) =>
|
|
||||||
{
|
|
||||||
if (sender is Window == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var w = (Window)sender;
|
|
||||||
HideCloseButton(w);
|
|
||||||
w.Loaded -= HideCloseButtonWhenLoadedDelegate;
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly RoutedEventHandler ShowCloseButtonWhenLoadedDelegate = (sender, args) =>
|
|
||||||
{
|
|
||||||
if (sender is Window == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var w = (Window)sender;
|
|
||||||
ShowCloseButton(w);
|
|
||||||
w.Loaded -= ShowCloseButtonWhenLoadedDelegate;
|
|
||||||
};
|
|
||||||
|
|
||||||
public static readonly DependencyProperty HideCloseButtonProperty =
|
|
||||||
DependencyProperty.RegisterAttached("HideCloseButton", typeof(bool), OwnerType,
|
|
||||||
new FrameworkPropertyMetadata(false, new PropertyChangedCallback(HideCloseButtonChangedCallback)));
|
|
||||||
|
|
||||||
[AttachedPropertyBrowsableForType(typeof(Window))]
|
|
||||||
public static bool GetHideCloseButton(Window obj) => (bool)obj.GetValue(HideCloseButtonProperty);
|
|
||||||
|
|
||||||
[AttachedPropertyBrowsableForType(typeof(Window))]
|
|
||||||
public static void SetHideCloseButton(Window obj, bool value) => obj.SetValue(HideCloseButtonProperty, value);
|
|
||||||
|
|
||||||
private static void HideCloseButtonChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
var window = d as Window;
|
|
||||||
if (window == null) return;
|
|
||||||
|
|
||||||
var hideCloseButton = (bool)e.NewValue;
|
|
||||||
if (hideCloseButton && !GetIsHiddenCloseButton(window))
|
|
||||||
{
|
|
||||||
if (!window.IsLoaded)
|
|
||||||
window.Loaded += HideCloseButtonWhenLoadedDelegate;
|
|
||||||
else
|
|
||||||
HideCloseButton(window);
|
|
||||||
|
|
||||||
SetIsHiddenCloseButton(window, true);
|
|
||||||
}
|
|
||||||
else if (!hideCloseButton && GetIsHiddenCloseButton(window))
|
|
||||||
{
|
|
||||||
if (!window.IsLoaded)
|
|
||||||
window.Loaded -= ShowCloseButtonWhenLoadedDelegate;
|
|
||||||
else
|
|
||||||
ShowCloseButton(window);
|
|
||||||
|
|
||||||
SetIsHiddenCloseButton(window, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static void HideCloseButton(Window w)
|
|
||||||
{
|
|
||||||
var hwnd = new WindowInteropHelper(w).Handle;
|
|
||||||
SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SYSMENU);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ShowCloseButton(Window w)
|
|
||||||
{
|
|
||||||
var hwnd = new WindowInteropHelper(w).Handle;
|
|
||||||
SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_SYSMENU);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region IsHiddenCloseButton (readonly attached property)
|
|
||||||
|
|
||||||
private static readonly DependencyPropertyKey IsHiddenCloseButtonKey =
|
|
||||||
DependencyProperty.RegisterAttachedReadOnly("IsHiddenCloseButton", typeof(bool), OwnerType, new FrameworkPropertyMetadata(false));
|
|
||||||
|
|
||||||
public static readonly DependencyProperty IsHiddenCloseButtonProperty = IsHiddenCloseButtonKey.DependencyProperty;
|
|
||||||
|
|
||||||
[AttachedPropertyBrowsableForType(typeof(Window))]
|
|
||||||
public static bool GetIsHiddenCloseButton(Window obj) => (bool)obj.GetValue(IsHiddenCloseButtonProperty);
|
|
||||||
|
|
||||||
private static void SetIsHiddenCloseButton(Window obj, bool value) => obj.SetValue(IsHiddenCloseButtonKey, value);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
//#region HideMinimizeButton
|
|
||||||
|
|
||||||
//private static readonly RoutedEventHandler HideMinimizeButtonWhenLoadedDelegate = (sender, args) => {
|
|
||||||
// if (sender is Window == false)
|
|
||||||
// return;
|
|
||||||
|
|
||||||
// var w = (Window)sender;
|
|
||||||
// HideMinimizeButton(w);
|
|
||||||
// w.Loaded -= HideMinimizeButtonWhenLoadedDelegate;
|
|
||||||
//};
|
|
||||||
|
|
||||||
//private static readonly RoutedEventHandler ShowMinimizeButtonWhenLoadedDelegate = (sender, args) => {
|
|
||||||
// if (sender is Window == false)
|
|
||||||
// return;
|
|
||||||
|
|
||||||
// var w = (Window)sender;
|
|
||||||
// ShowMinimizeButton(w);
|
|
||||||
// w.Loaded -= ShowMinimizeButtonWhenLoadedDelegate;
|
|
||||||
//};
|
|
||||||
|
|
||||||
//public static readonly DependencyProperty HideMinimizeButtonProperty =
|
|
||||||
// DependencyProperty.RegisterAttached("HideMinimizeButton", typeof(bool), OwnerType,
|
|
||||||
// new FrameworkPropertyMetadata(false, new PropertyChangedCallback(HideMinimizeButtonChangedCallback)));
|
|
||||||
|
|
||||||
//[AttachedPropertyBrowsableForType(typeof(Window))]
|
|
||||||
//public static bool GetHideMinimizeButton(Window obj) => (bool)obj.GetValue(HideCloseButtonProperty);
|
|
||||||
|
|
||||||
//[AttachedPropertyBrowsableForType(typeof(Window))]
|
|
||||||
//public static void SetHideMinimizeButton(Window obj, bool value) => obj.SetValue(HideCloseButtonProperty, value);
|
|
||||||
|
|
||||||
//private static void HideMinimizeButtonChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
||||||
//{
|
|
||||||
// var window = d as Window;
|
|
||||||
// if (window == null) return;
|
|
||||||
|
|
||||||
// var hideCloseButton = (bool)e.NewValue;
|
|
||||||
// if (hideCloseButton && !GetIsHiddenMinimizeButton(window))
|
|
||||||
// {
|
|
||||||
// if (!window.IsLoaded)
|
|
||||||
// window.Loaded += HideMinimizeButtonWhenLoadedDelegate;
|
|
||||||
// else
|
|
||||||
// HideMinimizeButton(window);
|
|
||||||
|
|
||||||
// SetIsHiddenMinimizeButton(window, true);
|
|
||||||
// }
|
|
||||||
// else if (!hideCloseButton && GetIsHiddenMinimizeButton(window))
|
|
||||||
// {
|
|
||||||
// if (!window.IsLoaded)
|
|
||||||
// window.Loaded -= ShowMinimizeButtonWhenLoadedDelegate;
|
|
||||||
// else
|
|
||||||
// ShowMinimizeButton(window);
|
|
||||||
|
|
||||||
// SetIsHiddenMinimizeButton(window, false);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//private static void HideMinimizeButton(Window w)
|
|
||||||
//{
|
|
||||||
// var hwnd = new WindowInteropHelper(w).Handle;
|
|
||||||
// SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_MINIMIZEBOX);
|
|
||||||
//}
|
|
||||||
|
|
||||||
//private static void ShowMinimizeButton(Window w)
|
|
||||||
//{
|
|
||||||
// var hwnd = new WindowInteropHelper(w).Handle;
|
|
||||||
// SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_MINIMIZEBOX);
|
|
||||||
//}
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
//#region IsHiddenMinimizeButton (readonly attached property)
|
|
||||||
//private static readonly DependencyPropertyKey IsHiddenMinimizeButtonKey =
|
|
||||||
// DependencyProperty.RegisterAttachedReadOnly("IsHiddenMinimizeButton", typeof(bool), OwnerType, new FrameworkPropertyMetadata(false));
|
|
||||||
|
|
||||||
//public static readonly DependencyProperty IsHiddenMinimizeButtonProperty = IsHiddenMinimizeButtonKey.DependencyProperty;
|
|
||||||
|
|
||||||
//[AttachedPropertyBrowsableForType(typeof(Window))]
|
|
||||||
//public static bool GetIsHiddenMinimizeButton(Window obj) => (bool)obj.GetValue(IsHiddenMinimizeButtonProperty);
|
|
||||||
|
|
||||||
//private static void SetIsHiddenMinimizeButton(Window obj, bool value) => obj.SetValue(IsHiddenMinimizeButtonProperty, value);
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
//#region HideMaximizeButton
|
|
||||||
|
|
||||||
//private static readonly RoutedEventHandler HideMaximizeButtonWhenLoadedDelegate = (sender, args) => {
|
|
||||||
// if (sender is Window == false)
|
|
||||||
// return;
|
|
||||||
|
|
||||||
// var w = (Window)sender;
|
|
||||||
// HideMaximizeButton(w);
|
|
||||||
// w.Loaded -= HideMaximizeButtonWhenLoadedDelegate;
|
|
||||||
//};
|
|
||||||
|
|
||||||
//private static readonly RoutedEventHandler ShowMaximizeButtonWhenLoadedDelegate = (sender, args) => {
|
|
||||||
// if (sender is Window == false)
|
|
||||||
// return;
|
|
||||||
|
|
||||||
// var w = (Window)sender;
|
|
||||||
// ShowMaximizeButton(w);
|
|
||||||
// w.Loaded -= ShowMaximizeButtonWhenLoadedDelegate;
|
|
||||||
//};
|
|
||||||
|
|
||||||
//public static readonly DependencyProperty HideMaximizeButtonProperty =
|
|
||||||
// DependencyProperty.RegisterAttached("HideMaximizeButton", typeof(bool), OwnerType,
|
|
||||||
// new FrameworkPropertyMetadata(false, new PropertyChangedCallback(HideMaximizeButtonChangedCallback)));
|
|
||||||
|
|
||||||
//[AttachedPropertyBrowsableForType(typeof(Window))]
|
|
||||||
//public static bool GetHideMaximizeButton(Window obj) => (bool)obj.GetValue(HideCloseButtonProperty);
|
|
||||||
|
|
||||||
//[AttachedPropertyBrowsableForType(typeof(Window))]
|
|
||||||
//public static void SetHideMaximizeButton(Window obj, bool value) => obj.SetValue(HideCloseButtonProperty, value);
|
|
||||||
|
|
||||||
//private static void HideMaximizeButtonChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
||||||
//{
|
|
||||||
// var window = d as Window;
|
|
||||||
// if (window == null) return;
|
|
||||||
|
|
||||||
// var hideCloseButton = (bool)e.NewValue;
|
|
||||||
// if (hideCloseButton && !GetIsHiddenMaximizeButton(window))
|
|
||||||
// {
|
|
||||||
// if (!window.IsLoaded)
|
|
||||||
// window.Loaded += HideMaximizeButtonWhenLoadedDelegate;
|
|
||||||
// else
|
|
||||||
// HideMaximizeButton(window);
|
|
||||||
|
|
||||||
// SetIsHiddenMaximizeButton(window, true);
|
|
||||||
// }
|
|
||||||
// else if (!hideCloseButton && GetIsHiddenMaximizeButton(window))
|
|
||||||
// {
|
|
||||||
// if (!window.IsLoaded)
|
|
||||||
// window.Loaded -= ShowMaximizeButtonWhenLoadedDelegate;
|
|
||||||
// else
|
|
||||||
// ShowMaximizeButton(window);
|
|
||||||
|
|
||||||
// SetIsHiddenMaximizeButton(window, false);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//private static void HideMaximizeButton(Window w)
|
|
||||||
//{
|
|
||||||
// var hwnd = new WindowInteropHelper(w).Handle;
|
|
||||||
// SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_MINIMIZEBOX);
|
|
||||||
//}
|
|
||||||
|
|
||||||
//private static void ShowMaximizeButton(Window w)
|
|
||||||
//{
|
|
||||||
// var hwnd = new WindowInteropHelper(w).Handle;
|
|
||||||
// SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_MINIMIZEBOX);
|
|
||||||
//}
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
//#region IsHiddenMaximizeButton (readonly attached property)
|
|
||||||
//private static readonly DependencyPropertyKey IsHiddenMaximizeButtonKey =
|
|
||||||
// DependencyProperty.RegisterAttachedReadOnly("IsHiddenMaximizeButton", typeof(bool), OwnerType, new FrameworkPropertyMetadata(false));
|
|
||||||
|
|
||||||
//public static readonly DependencyProperty IsHiddenMaximizeButtonProperty = IsHiddenMaximizeButtonKey.DependencyProperty;
|
|
||||||
|
|
||||||
//[AttachedPropertyBrowsableForType(typeof(Window))]
|
|
||||||
//public static bool GetIsHiddenMaximizeButton(Window obj) => (bool)obj.GetValue(IsHiddenMaximizeButtonProperty);
|
|
||||||
|
|
||||||
//private static void SetIsHiddenMaximizeButton(Window obj, bool value) => obj.SetValue(IsHiddenMaximizeButtonProperty, value);
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
using System.Text.Json.Serialization;
|
|
||||||
using WPFBeginner.Models;
|
|
||||||
|
|
||||||
namespace WPFBeginner.Configurations
|
|
||||||
{
|
|
||||||
public class AppSettings
|
|
||||||
{
|
|
||||||
public EventHandler<StringChangedEventArg> LanguageChanged;
|
|
||||||
public EventHandler<StringChangedEventArg> ThemeChanged;
|
|
||||||
|
|
||||||
[JsonPropertyName("Login")]
|
|
||||||
public LoginInfo Login { get; set; }
|
|
||||||
|
|
||||||
private string language;
|
|
||||||
[JsonPropertyName("Language")]
|
|
||||||
public string Language
|
|
||||||
{
|
|
||||||
get => language;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
var eventArg = new StringChangedEventArg()
|
|
||||||
{
|
|
||||||
Old = language,
|
|
||||||
New = value
|
|
||||||
};
|
|
||||||
|
|
||||||
language = value;
|
|
||||||
|
|
||||||
if (eventArg.NotChanged)
|
|
||||||
return;
|
|
||||||
|
|
||||||
LanguageChanged?.Invoke(null, eventArg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string theme;
|
|
||||||
[JsonPropertyName("Theme")]
|
|
||||||
public string Theme
|
|
||||||
{
|
|
||||||
get => theme;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
var eventArg = new StringChangedEventArg()
|
|
||||||
{
|
|
||||||
Old = theme,
|
|
||||||
New = value
|
|
||||||
};
|
|
||||||
|
|
||||||
theme = value;
|
|
||||||
|
|
||||||
if (eventArg.NotChanged)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ThemeChanged?.Invoke(null, eventArg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonPropertyName("DefaultMembers")]
|
|
||||||
public List<Member> Members { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class StringChangedEventArg : EventArgs
|
|
||||||
{
|
|
||||||
public string Old { get; set; }
|
|
||||||
public string New { get; set; }
|
|
||||||
|
|
||||||
public bool NotChanged => Old?.Equals(New, StringComparison.OrdinalIgnoreCase) ?? true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace WPFBeginner.Configurations
|
|
||||||
{
|
|
||||||
public class LoginInfo
|
|
||||||
{
|
|
||||||
[JsonPropertyName("User")]
|
|
||||||
public string User { get; set; }
|
|
||||||
|
|
||||||
public string Password { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
<UserControl x:Class="WPFBeginner.Controls.MemberInputPanel"
|
|
||||||
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"
|
|
||||||
mc:Ignorable="d" Name="root"
|
|
||||||
d:DesignHeight="450" d:DesignWidth="800">
|
|
||||||
|
|
||||||
<UserControl.Resources>
|
|
||||||
<Style x:Key="LabelTitle" TargetType="Label">
|
|
||||||
<Setter Property="FontSize" Value="12"/>
|
|
||||||
<Setter Property="FontFamily" Value="Yu Gothic UI"/>
|
|
||||||
<Setter Property="FontWeight" Value="Bold"/>
|
|
||||||
<Setter Property="Padding" Value="10 0"/>
|
|
||||||
<Setter Property="HorizontalAlignment" Value="Right"/>
|
|
||||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
|
||||||
<Setter Property="Foreground" Value="{DynamicResource Colors.TextBox.Foreground}"/>
|
|
||||||
</Style>
|
|
||||||
<Style x:Key="InputBox" TargetType="TextBox">
|
|
||||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
|
||||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
|
||||||
<Setter Property="Padding" Value="5 0"/>
|
|
||||||
<Setter Property="Height" Value="25"/>
|
|
||||||
<Setter Property="Foreground" Value="{DynamicResource Colors.TextBox.Foreground}"/>
|
|
||||||
<Setter Property="Background" Value="{DynamicResource Colors.TextBox.Background}"/>
|
|
||||||
<Setter Property="BorderBrush" Value="#FF424242"/>
|
|
||||||
</Style>
|
|
||||||
</UserControl.Resources>
|
|
||||||
<Grid >
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="*"/>
|
|
||||||
<RowDefinition Height="*"/>
|
|
||||||
<RowDefinition Height="*"/>
|
|
||||||
<RowDefinition Height="*"/>
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="Auto"/>
|
|
||||||
<ColumnDefinition Width="*"/>
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
|
|
||||||
<Label Grid.Row="0" Style="{StaticResource LabelTitle}" Content="{DynamicResource Cultures.MainWindow.Label.Name}"/>
|
|
||||||
<Label Grid.Row="1" Style="{StaticResource LabelTitle}" Content="{DynamicResource Cultures.MainWindow.Label.Call}" />
|
|
||||||
<Label Grid.Row="2" Style="{StaticResource LabelTitle}" Content="{DynamicResource Cultures.MainWindow.Label.No}"/>
|
|
||||||
<Label Grid.Row="3" Style="{StaticResource LabelTitle}" Content="{DynamicResource Cultures.MainWindow.Label.Mail}"/>
|
|
||||||
|
|
||||||
<TextBox Grid.Row="0" Grid.Column="1" Style="{StaticResource InputBox}" Text="{Binding ElementName=root, Path=MemberName}"/>
|
|
||||||
<TextBox Grid.Row="1" Grid.Column="1" Style="{StaticResource InputBox}" Text="{Binding ElementName=root, Path=Call}"/>
|
|
||||||
<TextBox Grid.Row="2" Grid.Column="1" Style="{StaticResource InputBox}" Text="{Binding ElementName=root, Path=EmployeeNo}"/>
|
|
||||||
<TextBox Grid.Row="3" Grid.Column="1" Style="{StaticResource InputBox}" Text="{Binding ElementName=root, Path=Email}"/>
|
|
||||||
</Grid>
|
|
||||||
</UserControl>
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
using System.Windows;
|
|
||||||
using System.Windows.Controls;
|
|
||||||
|
|
||||||
namespace WPFBeginner.Controls
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// MemberInputPanel.xaml에 대한 상호 작용 논리
|
|
||||||
/// </summary>
|
|
||||||
public partial class MemberInputPanel : UserControl
|
|
||||||
{
|
|
||||||
public static readonly DependencyProperty MemberNameProperty =
|
|
||||||
DependencyProperty.Register(nameof(MemberName), typeof(string), typeof(MemberInputPanel), new FrameworkPropertyMetadata() { BindsTwoWayByDefault = true });
|
|
||||||
|
|
||||||
public string MemberName
|
|
||||||
{
|
|
||||||
get => (string)GetValue(MemberNameProperty);
|
|
||||||
set => SetValue(MemberNameProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly DependencyProperty EmployeeNoProperty =
|
|
||||||
DependencyProperty.Register(nameof(EmployeeNo), typeof(string), typeof(MemberInputPanel), new FrameworkPropertyMetadata() { BindsTwoWayByDefault = true });
|
|
||||||
|
|
||||||
public string EmployeeNo
|
|
||||||
{
|
|
||||||
get => (string)GetValue(EmployeeNoProperty);
|
|
||||||
set => SetValue(EmployeeNoProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly DependencyProperty CallProperty =
|
|
||||||
DependencyProperty.Register(nameof(Call), typeof(string), typeof(MemberInputPanel), new FrameworkPropertyMetadata() { BindsTwoWayByDefault = true });
|
|
||||||
|
|
||||||
public string Call
|
|
||||||
{
|
|
||||||
get => (string)GetValue(CallProperty);
|
|
||||||
set => SetValue(CallProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly DependencyProperty EmailProperty =
|
|
||||||
DependencyProperty.Register(nameof(Email), typeof(string), typeof(MemberInputPanel), new FrameworkPropertyMetadata() { BindsTwoWayByDefault = true });
|
|
||||||
|
|
||||||
public string Email
|
|
||||||
{
|
|
||||||
get => (string)GetValue(EmailProperty);
|
|
||||||
set => SetValue(EmailProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MemberInputPanel()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
using System.Windows.Markup;
|
|
||||||
|
|
||||||
namespace WPFBeginner.Converters
|
|
||||||
{
|
|
||||||
public abstract class BaseConverter : MarkupExtension
|
|
||||||
{
|
|
||||||
protected BaseConverter() { }
|
|
||||||
|
|
||||||
public override object ProvideValue(IServiceProvider serviceProvider)
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
using System.Windows.Data;
|
|
||||||
|
|
||||||
namespace WPFBeginner.Converters
|
|
||||||
{
|
|
||||||
[ValueConversion(typeof(bool), typeof(bool))]
|
|
||||||
public class InverseBoolConverter : BaseConverter, IValueConverter
|
|
||||||
{
|
|
||||||
public InverseBoolConverter() { }
|
|
||||||
|
|
||||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
|
||||||
{
|
|
||||||
return !(bool)value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
|
||||||
{
|
|
||||||
return !(bool)value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
namespace WPFBeginner.Exceptions
|
|
||||||
{
|
|
||||||
internal class LoginFailedException : Exception
|
|
||||||
{
|
|
||||||
public LoginFailedException() : base()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace WPFBeginner.Models
|
|
||||||
{
|
|
||||||
public class Member
|
|
||||||
{
|
|
||||||
[JsonPropertyName("Name")]
|
|
||||||
public string Name { get; set; }
|
|
||||||
[JsonPropertyName("Call")]
|
|
||||||
public string Call { get; set; }
|
|
||||||
[JsonPropertyName("EMail")]
|
|
||||||
public string EMail { get; set; }
|
|
||||||
[JsonPropertyName("No")]
|
|
||||||
public string EmployeeNo { get; set; }
|
|
||||||
|
|
||||||
public static Member Create(string name, string call, string email, string employeeNo)
|
|
||||||
{
|
|
||||||
return new Member()
|
|
||||||
{
|
|
||||||
Name = name,
|
|
||||||
Call = call,
|
|
||||||
EMail = email,
|
|
||||||
EmployeeNo = employeeNo
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
|
||||||
|
|
||||||
<DrawingImage x:Key="Images.OptionsMenu.Setting.Normal">
|
|
||||||
<DrawingImage.Drawing>
|
|
||||||
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
|
|
||||||
<GeometryDrawing Brush="{DynamicResource Colors.Images.OptionsMenu.Setting.Normal}" Geometry="F0 M24,24z M0,0z M10.1,1.3L10.1,1.1 12.7,1.1 12.7,1.3 13,2.6 13.2,3.7C14.2,3.9,15.1,4.3,15.9,4.8L16,4.8 17.7,3.5 17.8,3.4 18.1,3.4 18.9,4.2 19.7,5 19.7,5.3 19.6,5.4 19,6.2 18.4,7.1C18.9,7.9,19.3,8.8,19.6,9.8L19.6,9.9 20.5,10 20.7,10 21.7,10.2 21.9,10.2 21.9,12.8 21.7,12.8 20.7,13 19.6,13.2C19.4,14.2,19,15.1,18.5,15.9L19.8,17.6C19.8,17.6,19.8,17.7,19.9,17.7L19.9,18 19.1,18.8 18.3,19.6 18,19.6 17.9,19.5 16,18.4C15.2,18.9,14.2,19.3,13.3,19.5L13.3,19.6 13,21.7 13,21.9 10.4,21.9 10.4,21.7 10.2,20.5 10,19.4C9.1,19.2,8.2,18.8,7.4,18.3L7,18.4 5.3,19.7 5.2,19.8 4.9,19.8 4.1,19 3.3,18.2 3.3,17.9 3.4,17.8 4.2,16.7 4.6,16 4.8,15.7C4.4,15,4,14.2,3.8,13.3L3.4,13.2 1.4,12.9 1.2,12.9 1.2,10.3 1.4,10.3 3.5,9.99999999999999 3.8,9.9C4,8.99999999999999,4.3,8.2,4.8,7.4L4.1,6.4 3.3,5.4 3.2,5.3 3.2,5 4,4.1 4.8,3.3 5.1,3.3 5.2,3.4 7,4.7 7.2,4.9C8,4.3,8.8,3.9,9.8,3.7L10,2.6 10.1,1.3z M13.9,1.3L14.1,2.8C14.7,3,15.3,3.2,15.8,3.5L17,2.6C17.1,2.5 17.4,2.3 17.7,2.2 18,2.1 18.4,2.2 18.8,2.5L19.6,3.3 20.4,4.1C20.7,4.4 20.8,4.8 20.7,5.2 20.6,5.5 20.5,5.7 20.3,5.9L19.5,7C19.8,7.6,20.1,8.2,20.3,8.8L21.7,9C21.9,9 22.2,9.1 22.4,9.2 22.7,9.4 22.9,9.7 22.9,10.2L22.9,12.6C22.9,13.1 22.7,13.4 22.4,13.6 22.2,13.8 21.9,13.8 21.7,13.8L20.3,14C20.1,14.6,19.9,15.2,19.6,15.7L20.4,16.8C20.5,16.9 20.7,17.2 20.8,17.5 20.9,17.8 20.8,18.2 20.5,18.6L19.7,19.4 18.9,20.2C18.6,20.5 18.2,20.6 17.8,20.5 17.5,20.4 17.3,20.3 17.1,20.1L15.9,19.2C15.3,19.5,14.7,19.7,14.1,19.9L13.9,21.4C13.9,21.6 13.8,21.9 13.7,22.1 13.5,22.4 13.2,22.6 12.7,22.6L10.3,22.6C9.8,22.6 9.5,22.4 9.3,22.1 9.1,21.9 9.1,21.6 9.1,21.4L8.9,19.8C8.3,19.6,7.8,19.4,7.2,19.1L5.9,20.1C5.8,20.2 5.5,20.4 5.2,20.5 4.9,20.6 4.5,20.5 4.1,20.2L3.3,19.4 2.5,18.6C2.2,18.3 2.1,17.9 2.2,17.5 2.3,17.2 2.4,17 2.6,16.8L3.6,15.4C3.4,14.9,3.2,14.5,3,14L1.2,14C1,14 0.7,13.9 0.5,13.8 0.2,13.6 0,13.3 0,12.8L0,10.4C0,9.9 0.2,9.6 0.5,9.4 0.8,9.2 1,9.2 1.2,9.2L3,8.9 3.6,7.4 2.5,6C2.4,5.8 2.2,5.6 2.2,5.3 2.1,5 2.2,4.6 2.5,4.2L3.3,3.4 4.1,2.6C4.4,2.3 4.8,2.2 5.2,2.3 5.5,2.4 5.7,2.5 5.9,2.7L7.2,3.7C7.7,3.4,8.2,3.2,8.8,3L9,1.4C9,1.2 9.1,0.9 9.2,0.7 9.5,0.3 9.8,0 10.3,0L12.7,0C13.2,0 13.5,0.2 13.7,0.5 13.8,0.8 13.9,1.1 13.9,1.3z" />
|
|
||||||
<GeometryDrawing>
|
|
||||||
<GeometryDrawing.Pen>
|
|
||||||
<Pen Brush="{DynamicResource Colors.Images.OptionsMenu.Setting.Normal}" Thickness="1" StartLineCap="Flat" EndLineCap="Flat" LineJoin="Miter" />
|
|
||||||
</GeometryDrawing.Pen>
|
|
||||||
<GeometryDrawing.Geometry>
|
|
||||||
<EllipseGeometry RadiusX="3.4" RadiusY="3.4" Center="11.5,11.5" />
|
|
||||||
</GeometryDrawing.Geometry>
|
|
||||||
</GeometryDrawing>
|
|
||||||
</DrawingGroup>
|
|
||||||
</DrawingImage.Drawing>
|
|
||||||
</DrawingImage>
|
|
||||||
|
|
||||||
<DrawingImage x:Key="Images.OptionsMenu.Setting.Pressed">
|
|
||||||
<DrawingImage.Drawing>
|
|
||||||
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
|
|
||||||
<GeometryDrawing Brush="{DynamicResource Colors.Images.OptionsMenu.Setting.Pressed}" Geometry="F0 M24,24z M0,0z M10.1,1.3L10.1,1.1 12.7,1.1 12.7,1.3 13,2.6 13.2,3.7C14.2,3.9,15.1,4.3,15.9,4.8L16,4.8 17.7,3.5 17.8,3.4 18.1,3.4 18.9,4.2 19.7,5 19.7,5.3 19.6,5.4 19,6.2 18.4,7.1C18.9,7.9,19.3,8.8,19.6,9.8L19.6,9.9 20.5,10 20.7,10 21.7,10.2 21.9,10.2 21.9,12.8 21.7,12.8 20.7,13 19.6,13.2C19.4,14.2,19,15.1,18.5,15.9L19.8,17.6C19.8,17.6,19.8,17.7,19.9,17.7L19.9,18 19.1,18.8 18.3,19.6 18,19.6 17.9,19.5 16,18.4C15.2,18.9,14.2,19.3,13.3,19.5L13.3,19.6 13,21.7 13,21.9 10.4,21.9 10.4,21.7 10.2,20.5 10,19.4C9.1,19.2,8.2,18.8,7.4,18.3L7,18.4 5.3,19.7 5.2,19.8 4.9,19.8 4.1,19 3.3,18.2 3.3,17.9 3.4,17.8 4.2,16.7 4.6,16 4.8,15.7C4.4,15,4,14.2,3.8,13.3L3.4,13.2 1.4,12.9 1.2,12.9 1.2,10.3 1.4,10.3 3.5,9.99999999999999 3.8,9.9C4,8.99999999999999,4.3,8.2,4.8,7.4L4.1,6.4 3.3,5.4 3.2,5.3 3.2,5 4,4.1 4.8,3.3 5.1,3.3 5.2,3.4 7,4.7 7.2,4.9C8,4.3,8.8,3.9,9.8,3.7L10,2.6 10.1,1.3z M13.9,1.3L14.1,2.8C14.7,3,15.3,3.2,15.8,3.5L17,2.6C17.1,2.5 17.4,2.3 17.7,2.2 18,2.1 18.4,2.2 18.8,2.5L19.6,3.3 20.4,4.1C20.7,4.4 20.8,4.8 20.7,5.2 20.6,5.5 20.5,5.7 20.3,5.9L19.5,7C19.8,7.6,20.1,8.2,20.3,8.8L21.7,9C21.9,9 22.2,9.1 22.4,9.2 22.7,9.4 22.9,9.7 22.9,10.2L22.9,12.6C22.9,13.1 22.7,13.4 22.4,13.6 22.2,13.8 21.9,13.8 21.7,13.8L20.3,14C20.1,14.6,19.9,15.2,19.6,15.7L20.4,16.8C20.5,16.9 20.7,17.2 20.8,17.5 20.9,17.8 20.8,18.2 20.5,18.6L19.7,19.4 18.9,20.2C18.6,20.5 18.2,20.6 17.8,20.5 17.5,20.4 17.3,20.3 17.1,20.1L15.9,19.2C15.3,19.5,14.7,19.7,14.1,19.9L13.9,21.4C13.9,21.6 13.8,21.9 13.7,22.1 13.5,22.4 13.2,22.6 12.7,22.6L10.3,22.6C9.8,22.6 9.5,22.4 9.3,22.1 9.1,21.9 9.1,21.6 9.1,21.4L8.9,19.8C8.3,19.6,7.8,19.4,7.2,19.1L5.9,20.1C5.8,20.2 5.5,20.4 5.2,20.5 4.9,20.6 4.5,20.5 4.1,20.2L3.3,19.4 2.5,18.6C2.2,18.3 2.1,17.9 2.2,17.5 2.3,17.2 2.4,17 2.6,16.8L3.6,15.4C3.4,14.9,3.2,14.5,3,14L1.2,14C1,14 0.7,13.9 0.5,13.8 0.2,13.6 0,13.3 0,12.8L0,10.4C0,9.9 0.2,9.6 0.5,9.4 0.8,9.2 1,9.2 1.2,9.2L3,8.9 3.6,7.4 2.5,6C2.4,5.8 2.2,5.6 2.2,5.3 2.1,5 2.2,4.6 2.5,4.2L3.3,3.4 4.1,2.6C4.4,2.3 4.8,2.2 5.2,2.3 5.5,2.4 5.7,2.5 5.9,2.7L7.2,3.7C7.7,3.4,8.2,3.2,8.8,3L9,1.4C9,1.2 9.1,0.9 9.2,0.7 9.5,0.3 9.8,0 10.3,0L12.7,0C13.2,0 13.5,0.2 13.7,0.5 13.8,0.8 13.9,1.1 13.9,1.3z" />
|
|
||||||
<GeometryDrawing>
|
|
||||||
<GeometryDrawing.Pen>
|
|
||||||
<Pen Brush="{DynamicResource Colors.Images.OptionsMenu.Setting.Pressed}" Thickness="1" StartLineCap="Flat" EndLineCap="Flat" LineJoin="Miter" />
|
|
||||||
</GeometryDrawing.Pen>
|
|
||||||
<GeometryDrawing.Geometry>
|
|
||||||
<EllipseGeometry RadiusX="3.4" RadiusY="3.4" Center="11.5,11.5" />
|
|
||||||
</GeometryDrawing.Geometry>
|
|
||||||
</GeometryDrawing>
|
|
||||||
</DrawingGroup>
|
|
||||||
</DrawingImage.Drawing>
|
|
||||||
</DrawingImage>
|
|
||||||
|
|
||||||
</ResourceDictionary>
|
|
||||||
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 24 KiB |
@@ -1,43 +0,0 @@
|
|||||||
using System.Windows;
|
|
||||||
|
|
||||||
namespace WPFBeginner.Resources
|
|
||||||
{
|
|
||||||
public class SharedResourceDictionary : ResourceDictionary
|
|
||||||
{
|
|
||||||
private static Dictionary<Uri, WeakReference> _cache = new Dictionary<Uri, WeakReference>();
|
|
||||||
|
|
||||||
private Uri source;
|
|
||||||
|
|
||||||
public new Uri Source
|
|
||||||
{
|
|
||||||
get => source;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
source = value;
|
|
||||||
if (!_cache.ContainsKey(source))
|
|
||||||
{
|
|
||||||
AddToCache();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WeakReference weakReference = _cache[source];
|
|
||||||
if (weakReference != null && weakReference.IsAlive)
|
|
||||||
MergedDictionaries.Add((ResourceDictionary)weakReference.Target);
|
|
||||||
else
|
|
||||||
AddToCache();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddToCache()
|
|
||||||
{
|
|
||||||
base.Source = source;
|
|
||||||
if (_cache.ContainsKey(source))
|
|
||||||
_cache.Remove(source);
|
|
||||||
|
|
||||||
_cache.Add(source, new WeakReference(this, false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
using System.Windows;
|
|
||||||
using System.Windows.Input;
|
|
||||||
|
|
||||||
namespace WPFBeginner.Services
|
|
||||||
{
|
|
||||||
public class EnterKeyTraversal
|
|
||||||
{
|
|
||||||
public static readonly DependencyProperty IsEnabledProperty =
|
|
||||||
DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(EnterKeyTraversal), new UIPropertyMetadata(false, IsEnabledChanged));
|
|
||||||
|
|
||||||
public static bool GetIsEnabled(DependencyObject obj) => (bool)obj.GetValue(IsEnabledProperty);
|
|
||||||
|
|
||||||
public static void SetIsEnabled(DependencyObject obj, bool value) => obj.SetValue(IsEnabledProperty, value);
|
|
||||||
|
|
||||||
static void PreviewKeyDown(object sender, KeyEventArgs e)
|
|
||||||
{
|
|
||||||
var uiElement = e.OriginalSource as FrameworkElement;
|
|
||||||
|
|
||||||
if (e.Key == Key.Enter)
|
|
||||||
{
|
|
||||||
e.Handled = true;
|
|
||||||
uiElement.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void Unloaded(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
var uiElement = sender as FrameworkElement;
|
|
||||||
if (uiElement == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
uiElement.Unloaded -= Unloaded;
|
|
||||||
uiElement.PreviewKeyDown -= PreviewKeyDown;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
var ue = d as FrameworkElement;
|
|
||||||
if (ue == null) return;
|
|
||||||
|
|
||||||
if ((bool)e.NewValue)
|
|
||||||
{
|
|
||||||
ue.Unloaded += Unloaded;
|
|
||||||
ue.PreviewKeyDown += PreviewKeyDown;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ue.PreviewKeyDown -= PreviewKeyDown;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
using System.Windows;
|
|
||||||
using System.Windows.Controls;
|
|
||||||
|
|
||||||
namespace WPFBeginner.Services
|
|
||||||
{
|
|
||||||
public static class PasswordBoxAssistant
|
|
||||||
{
|
|
||||||
#region BoundPassword Property
|
|
||||||
|
|
||||||
public static readonly DependencyProperty BoundPassword =
|
|
||||||
DependencyProperty.RegisterAttached(nameof(BoundPassword), typeof(string), typeof(PasswordBoxAssistant), new PropertyMetadata(string.Empty, OnBoundPasswordChanged));
|
|
||||||
|
|
||||||
public static string GetBoundPassword(DependencyObject dp) => (string)dp.GetValue(BoundPassword);
|
|
||||||
|
|
||||||
public static void SetBoundPassword(DependencyObject dp, string value) => dp.SetValue(BoundPassword, value);
|
|
||||||
|
|
||||||
private static void OnBoundPasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
var box = d as PasswordBox;
|
|
||||||
|
|
||||||
// only handle this event when the property is attached to a PasswordBox
|
|
||||||
// and when the BindPassword attached property has been set to true
|
|
||||||
if (d == null || !GetEnableBindingPassword(d))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// avoid recursive updating by ignoring the box's changed event
|
|
||||||
box.PasswordChanged -= HandlePasswordChanged;
|
|
||||||
|
|
||||||
string newPassword = (string)e.NewValue;
|
|
||||||
|
|
||||||
if (!GetUpdatingPassword(box))
|
|
||||||
box.Password = newPassword;
|
|
||||||
|
|
||||||
box.PasswordChanged += HandlePasswordChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region EnableBindingPassword
|
|
||||||
|
|
||||||
public static readonly DependencyProperty EnableBindingPassword =
|
|
||||||
DependencyProperty.RegisterAttached(nameof(EnableBindingPassword), typeof(bool), typeof(PasswordBoxAssistant), new PropertyMetadata(false, OnEnableBindingPasswordChanged));
|
|
||||||
|
|
||||||
public static bool GetEnableBindingPassword(DependencyObject dp) => (bool)dp.GetValue(EnableBindingPassword);
|
|
||||||
|
|
||||||
public static void SetEnableBindingPassword(DependencyObject dp, bool value) => dp.SetValue(EnableBindingPassword, value);
|
|
||||||
|
|
||||||
private static void OnEnableBindingPasswordChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
// when the BindPassword attached property is set on a PasswordBox,
|
|
||||||
// start listening to its PasswordChanged event
|
|
||||||
|
|
||||||
var box = dp as PasswordBox;
|
|
||||||
|
|
||||||
if (box == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bool wasBound = (bool)(e.OldValue);
|
|
||||||
bool needToBind = (bool)(e.NewValue);
|
|
||||||
|
|
||||||
if (wasBound)
|
|
||||||
box.PasswordChanged -= HandlePasswordChanged;
|
|
||||||
|
|
||||||
if (needToBind)
|
|
||||||
box.PasswordChanged += HandlePasswordChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region UpdatingPassword
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private static readonly DependencyProperty UpdatingPassword =
|
|
||||||
DependencyProperty.RegisterAttached(nameof(UpdatingPassword), typeof(bool), typeof(PasswordBoxAssistant), new PropertyMetadata(false));
|
|
||||||
|
|
||||||
private static bool GetUpdatingPassword(DependencyObject dp) => (bool)dp.GetValue(UpdatingPassword);
|
|
||||||
|
|
||||||
private static void SetUpdatingPassword(DependencyObject dp, bool value) => dp.SetValue(UpdatingPassword, value);
|
|
||||||
|
|
||||||
private static void HandlePasswordChanged(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
var box = sender as PasswordBox;
|
|
||||||
|
|
||||||
// set a flag to indicate that we're updating the password
|
|
||||||
SetUpdatingPassword(box, true);
|
|
||||||
// push the new password into the BoundPassword property
|
|
||||||
SetBoundPassword(box, box.Password);
|
|
||||||
SetUpdatingPassword(box, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
using System.Windows;
|
|
||||||
|
|
||||||
namespace WPFBeginner.Services
|
|
||||||
{
|
|
||||||
internal static class ResourceExplorer
|
|
||||||
{
|
|
||||||
public static string GetStringResource(string key)
|
|
||||||
{
|
|
||||||
var cultureCode = App.Config.Language;
|
|
||||||
var rd = App.Current.Resources.MergedDictionaries.FirstOrDefault(i => i.Source.AbsolutePath.EndsWith($"{cultureCode}.xaml"));
|
|
||||||
if (rd == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return rd[key] as string;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ChangeXamlResource(string oldRes, string newRes)
|
|
||||||
{
|
|
||||||
var found = App.Current.Resources.MergedDictionaries.Select((item, i) => new { Item = item, Index = i }).FirstOrDefault(i => i.Item.Source.AbsoluteUri.Equals($"{oldRes}", StringComparison.OrdinalIgnoreCase));
|
|
||||||
if (found == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var newResource = new ResourceDictionary()
|
|
||||||
{
|
|
||||||
Source = new Uri(newRes, UriKind.RelativeOrAbsolute)
|
|
||||||
};
|
|
||||||
App.Current.Resources.MergedDictionaries.Remove(found.Item);
|
|
||||||
App.Current.Resources.MergedDictionaries.Add(newResource);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ResourceDictionary GetLanguageResourceDic(string name)
|
|
||||||
{
|
|
||||||
var foundName = $"pack://application:,,,/Themes/Cultures/{name}.xaml";
|
|
||||||
//var foundName = $"/WPFBeginner;component/Themes/Cultures/{name}.xaml";
|
|
||||||
var found = App.Current.Resources.MergedDictionaries.Select((item, i) => new { Item = item, Index = i }).FirstOrDefault(i => i.Item.Source.AbsoluteUri.Equals(foundName, StringComparison.OrdinalIgnoreCase));
|
|
||||||
if (found == null)
|
|
||||||
return new ResourceDictionary() { Source = new Uri(foundName, UriKind.RelativeOrAbsolute) };
|
|
||||||
|
|
||||||
return found.Item;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ResourceDictionary GetThemeResourceDic(string name)
|
|
||||||
{
|
|
||||||
var foundName = $"pack://application:,,,/Themes/Colors/{name}.xaml";
|
|
||||||
//var foundName = $"/WPFBeginner;component/Themes/Colors/{name}.xaml";
|
|
||||||
var found = App.Current.Resources.MergedDictionaries.Select((item, i) => new { Item = item, Index = i }).FirstOrDefault(i => i.Item.Source.AbsoluteUri.Equals(foundName, StringComparison.OrdinalIgnoreCase));
|
|
||||||
if (found == null)
|
|
||||||
return new ResourceDictionary() { Source = new Uri(foundName, UriKind.RelativeOrAbsolute) };
|
|
||||||
|
|
||||||
return found.Item;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
|
||||||
using WPFBeginner.ViewModels;
|
|
||||||
|
|
||||||
namespace WPFBeginner.Services
|
|
||||||
{
|
|
||||||
internal class ViewModelLocator
|
|
||||||
{
|
|
||||||
public MainWindowViewModel MainWindowViewModel => Ioc.Default.GetService<MainWindowViewModel>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="Colors.TitleBar.Title.Background" Color="#FF1E1E1E"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.TitleBar.Title.Foreground" Color="LightGreen"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.Section.HorizontalSeperator" Color="Cyan" Opacity="0.8"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.Main.Background" Color="#FF1E1E1E" />
|
|
||||||
<SolidColorBrush x:Key="Colors.SettingPopup.Background" Color="#FF383838" />
|
|
||||||
<SolidColorBrush x:Key="Colors.SettingPopup.BorderBrush" Color="#FF424242" />
|
|
||||||
<SolidColorBrush x:Key="Colors.SettingPopup.Foreground" Color="White" />
|
|
||||||
<SolidColorBrush x:Key="Colors.TextBox.Background" Color="#FF383838"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.TextBox.Foreground" Color="White"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.TextBox.BorderBrush" Color="#FF424242"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Foreground.Normal" Color="White"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Foreground.MouseOver" Color="Pink"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Foreground.MousePressed" Color="Coral"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.BorderBrush.Normal" Color="#FF1F1F1F"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.BorderBrush.MouseOver" Color="Pink"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.BorderBrush.MousePressed" Color="Coral"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Background.Normal" Color="#FF1F1F1F"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Background.MouseOver" Color="#FF1F1F1F"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Background.MousePressed" Color="#FF1F1F1F"/>
|
|
||||||
|
|
||||||
<LinearGradientBrush x:Key="Colors.DataGridButton.Background.Normal" StartPoint="0,0" EndPoint="0,1">
|
|
||||||
<GradientStop Color="#38301f" Offset="0.0"/>
|
|
||||||
<GradientStop Color="#4a3c2b" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#342e1d" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#342e1d" Offset="1.0"/>
|
|
||||||
</LinearGradientBrush>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="Colors.DataGridButton.Foreground.Normal" Color="White" />
|
|
||||||
<!--<SolidColorBrush x:Key="Colors.DataGridButton.Background.MouseOver" Color="#FFEB530C" Opacity="0.6" />-->
|
|
||||||
<LinearGradientBrush x:Key="Colors.DataGridButton.Background.MouseOver" StartPoint="0,0" EndPoint="0,1" Opacity="0.6">
|
|
||||||
<GradientStop Color="#38301f" Offset="0.0"/>
|
|
||||||
<GradientStop Color="#4a3c2b" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#342e1d" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#342e1d" Offset="1.0"/>
|
|
||||||
</LinearGradientBrush>
|
|
||||||
<SolidColorBrush x:Key="Colors.DataGridButton.Foreground.MouseOver" Color="Yellow" />
|
|
||||||
<LinearGradientBrush x:Key="Colors.DataGridButton.Background.Pressed" StartPoint="0,0" EndPoint="0,1" Opacity="0.8">
|
|
||||||
<GradientStop Color="#38301f" Offset="0.0"/>
|
|
||||||
<GradientStop Color="#4a3c2b" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#342e1d" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#342e1d" Offset="1.0"/>
|
|
||||||
</LinearGradientBrush>
|
|
||||||
<!--<SolidColorBrush x:Key="Colors.DataGridButton.Background.Pressed" Color="#FFEB530C" Opacity="0.8" />-->
|
|
||||||
<SolidColorBrush x:Key="Colors.DataGridButton.Foreground.Pressed" Color="LightSkyBlue" />
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="Colors.Images.OptionsMenu.Setting.Normal" Color="#FFB8B8B9"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.Images.OptionsMenu.Setting.Pressed" Color="#FFB8B8B9" Opacity="0.6"/>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="Colors.Images.OptionsMenu.Setting.Background.MouseOver" Color="#FF474D51"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.Images.OptionsMenu.Setting.Background.MousePressed" Color="#FF474D51"/>
|
|
||||||
|
|
||||||
</ResourceDictionary>
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="Colors.TitleBar.Title.Background" Color="#FFF0F0F0"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.TitleBar.Title.Foreground" Color="DarkSlateBlue"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.Section.HorizontalSeperator" Color="Gray" Opacity="0.8"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.Main.Background" Color="#FFF0F0F0" />
|
|
||||||
<SolidColorBrush x:Key="Colors.SettingPopup.Background" Color="#FFF5F5F5" />
|
|
||||||
<SolidColorBrush x:Key="Colors.SettingPopup.BorderBrush" Color="#FFDDDDDD" />
|
|
||||||
<SolidColorBrush x:Key="Colors.SettingPopup.Foreground" Color="Black" />
|
|
||||||
<SolidColorBrush x:Key="Colors.TextBox.Background" Color="#FFF5F5F5"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.TextBox.Foreground" Color="Black"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.TextBox.BorderBrush" Color="#FFDDDDDD"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Foreground.Normal" Color="Black"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Foreground.MouseOver" Color="MediumSlateBlue"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Foreground.MousePressed" Color="SlateBlue"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.BorderBrush.Normal" Color="#FFEEEEEE"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.BorderBrush.MouseOver" Color="MediumSlateBlue"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.BorderBrush.MousePressed" Color="SlateBlue"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Background.Normal" Color="#FFEEEEEE"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Background.MouseOver" Color="#FFE0E0E0"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.SearchButton.Background.MousePressed" Color="#FFD6D6D6"/>
|
|
||||||
|
|
||||||
<LinearGradientBrush x:Key="Colors.DataGridButton.Background.Normal" StartPoint="0,0" EndPoint="0,1">
|
|
||||||
<GradientStop Color="#E3EAF3" Offset="0.0"/>
|
|
||||||
<GradientStop Color="#D4DFEA" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#C8D4E1" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#BFCCE0" Offset="1.0"/>
|
|
||||||
</LinearGradientBrush>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="Colors.DataGridButton.Foreground.Normal" Color="Black" />
|
|
||||||
<LinearGradientBrush x:Key="Colors.DataGridButton.Background.MouseOver" StartPoint="0,0" EndPoint="0,1" Opacity="0.6">
|
|
||||||
<GradientStop Color="#E3EAF3" Offset="0.0"/>
|
|
||||||
<GradientStop Color="#D4DFEA" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#C8D4E1" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#BFCCE0" Offset="1.0"/>
|
|
||||||
</LinearGradientBrush>
|
|
||||||
<SolidColorBrush x:Key="Colors.DataGridButton.Foreground.MouseOver" Color="DarkSlateBlue" />
|
|
||||||
<LinearGradientBrush x:Key="Colors.DataGridButton.Background.Pressed" StartPoint="0,0" EndPoint="0,1" Opacity="0.8">
|
|
||||||
<GradientStop Color="#E3EAF3" Offset="0.0"/>
|
|
||||||
<GradientStop Color="#D4DFEA" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#C8D4E1" Offset="0.5"/>
|
|
||||||
<GradientStop Color="#BFCCE0" Offset="1.0"/>
|
|
||||||
</LinearGradientBrush>
|
|
||||||
<SolidColorBrush x:Key="Colors.DataGridButton.Foreground.Pressed" Color="CornflowerBlue" />
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="Colors.Images.OptionsMenu.Setting.Normal" Color="#FF6E6E70"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.Images.OptionsMenu.Setting.Pressed" Color="#FF6E6E70" Opacity="0.6"/>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="Colors.Images.OptionsMenu.Setting.Background.MouseOver" Color="#FFD3D3D5"/>
|
|
||||||
<SolidColorBrush x:Key="Colors.Images.OptionsMenu.Setting.Background.MousePressed" Color="#FFD3D3D5"/>
|
|
||||||
</ResourceDictionary>
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
|
||||||
|
|
||||||
<sys:String x:Key="Cultures.LoginWindow.ErrorMessage.DuplicatedExecute">Duplicated execution.</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.LoginWindow.ErrorMessage.InvalidUser">Please check your ID and password again.</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.LoginWindow.LoginButtonText">Login</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.LoginWindow.Inform">Please enter your ID and password.</sys:String>
|
|
||||||
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.Title">Contact Management Program</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.Label.Name">Name:</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.Label.Call">Contact</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.Label.No">Employee Number:</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.Label.Mail">Email:</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.ErrorMessage.SearchConditionEmpty">No search condition provided. Please enter a search condition.</sys:String>
|
|
||||||
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.Button.Add">Add</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.Button.Search">Search</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.Button.Delete">Delete</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.Button.Init">Reset</sys:String>
|
|
||||||
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.DatagGid.Column.Name">Name</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.DatagGid.Column.Call">Contact</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.DatagGid.Column.No">Employee Number</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.DatagGid.Column.Email">Email</sys:String>
|
|
||||||
|
|
||||||
<sys:String x:Key="Cultures.RegistMemberWindow.RegistButton">Register</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.RegistMemberWindow.CancelButton">Cancel</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.RegistMemberWindow.ErrorMessage.FillMustValue">Name or employee number is required.</sys:String>
|
|
||||||
|
|
||||||
</ResourceDictionary>
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
|
||||||
|
|
||||||
<sys:String x:Key="Cultures.LoginWindow.ErrorMessage.DuplicatedExecute">중복된 실행입니다.</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.LoginWindow.ErrorMessage.InvalidUser">아이디와 비번을 다시 한번 확인해주세요</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.LoginWindow.LoginButtonText">로그인</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.LoginWindow.Inform">아이디와 비번을 입력해주세요</sys:String>
|
|
||||||
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.Title">연락처 관리 프로그램</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.Label.Name">이름:</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.Label.Call">연락처</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.Label.No">사번:</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.Label.Mail">이메일:</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.ErrorMessage.SearchConditionEmpty">검색 조건이 없습니다. 검색 조건을 입력해주세요</sys:String>
|
|
||||||
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.Button.Add">추가</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.Button.Search">검 색</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.Button.Delete">삭제</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.Button.Init">초기화</sys:String>
|
|
||||||
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.DatagGid.Column.Name">이름</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.DatagGid.Column.Call">연락처</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.DatagGid.Column.No">사번</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.MainWindow.DatagGid.Column.Email">이메일</sys:String>
|
|
||||||
|
|
||||||
<sys:String x:Key="Cultures.RegistMemberWindow.RegistButton">등록</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.RegistMemberWindow.CancelButton">취소</sys:String>
|
|
||||||
<sys:String x:Key="Cultures.RegistMemberWindow.ErrorMessage.FillMustValue">이름 또는 사번은 반드시 필요합니다.</sys:String>
|
|
||||||
|
|
||||||
</ResourceDictionary>
|
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
|
||||||
|
|
||||||
<!--Maximize Button-->
|
|
||||||
<Style x:Key="TiTleBarMaximizeButton" TargetType="{x:Type Button}">
|
|
||||||
<Setter Property="Background" Value="Transparent"/>
|
|
||||||
<Setter Property="Focusable" Value="False" />
|
|
||||||
<Setter Property="Template">
|
|
||||||
<Setter.Value>
|
|
||||||
<ControlTemplate TargetType="{x:Type Button}">
|
|
||||||
<Border Background="{TemplateBinding Background}">
|
|
||||||
<Path Fill="#FFB8B8B9" Height="14" Width="14" Canvas.Left="-7" Canvas.Top="5">
|
|
||||||
<Path.Style>
|
|
||||||
<Style TargetType="Path">
|
|
||||||
<Style.Triggers>
|
|
||||||
<DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" Value="Normal">
|
|
||||||
<!--<Setter Property="Data" Value="F1M3,5C3,5 3,11 3,11 3,11 9,11 9,11 9,11 9,5 9,5 9,5 3,5 3,5z M5,3C5,3,5,3.375,5,3.938L5,4 6,4C8,4 10,4 10,4 10,4 10,6 10,8L10,9 10.062,9C10.625,9 11,9 11,9 11,9 11,3 11,3 11,3 5,3 5,3z M4,2C4,2 12,2 12,2 12,2 12,10 12,10 12,10 11.5,10 10.75,10L10,10 10,10.75C10,11.5 10,12 10,12 10,12 2,12 2,12 2,12 2,4 2,4 2,4 2.5,4 3.25,4L4,4 4,3.25C4,2.5,4,2,4,2z"/>-->
|
|
||||||
<Setter Property="Data" Value="F1M3,3C3,3 3,11 3,11 3,11 11,11 11,11 11,11 11,3 11,3 11,3 3,3 3,3z M2,2C2,2 12,2 12,2 12,2 12,12 12,12 12,12 2,12 2,12 2,12 2,2 2,2z" />
|
|
||||||
</DataTrigger>
|
|
||||||
<DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" Value="Maximized">
|
|
||||||
<Setter Property="Data" Value="F1M3,5C3,5 3,11 3,11 3,11 9,11 9,11 9,11 9,5 9,5 9,5 3,5 3,5z M5,3C5,3 5,4 5,4 5,4 10,4 10,4 10,4 10,9 10,9 10,9 11,9 11,9 11,9 11,3 11,3 11,3 5,3 5,3z M4,2C4,2 12,2 12,2 12,2 12,10 12,10 12,10 10,10 10,10 10,10 10,12 10,12 10,12 2,12 2,12 2,12 2,4 2,4 2,4 4,4 4,4 4,4 4,2 4,2z"/>
|
|
||||||
</DataTrigger>
|
|
||||||
</Style.Triggers>
|
|
||||||
</Style>
|
|
||||||
</Path.Style>
|
|
||||||
</Path>
|
|
||||||
</Border>
|
|
||||||
</ControlTemplate>
|
|
||||||
</Setter.Value>
|
|
||||||
</Setter>
|
|
||||||
|
|
||||||
<Style.Triggers>
|
|
||||||
<Trigger Property="IsMouseOver" Value="True">
|
|
||||||
<Setter Property="Background" Value="#FF474D51"/>
|
|
||||||
</Trigger>
|
|
||||||
<Trigger Property="IsPressed" Value="True">
|
|
||||||
<Setter Property="Background" Value="#FF3D4347"/>
|
|
||||||
</Trigger>
|
|
||||||
<DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" Value="Normal">
|
|
||||||
<Setter Property="ToolTip" Value="Maximize"/>
|
|
||||||
</DataTrigger>
|
|
||||||
<DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" Value="Maximized">
|
|
||||||
<Setter Property="ToolTip" Value="Restore"/>
|
|
||||||
</DataTrigger>
|
|
||||||
</Style.Triggers>
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<!--Minimize Button-->
|
|
||||||
<Style x:Key="TiTleBarMinimizeButton" TargetType="{x:Type Button}">
|
|
||||||
<Setter Property="Background" Value="Transparent"/>
|
|
||||||
<Setter Property="Focusable" Value="False" />
|
|
||||||
<Setter Property="Template">
|
|
||||||
<Setter.Value>
|
|
||||||
<ControlTemplate TargetType="{x:Type Button}">
|
|
||||||
<Border Background="{TemplateBinding Background}">
|
|
||||||
<Path Data="F1M2,2C2,2 12,2 12,2 12,2 12,3 12,3 12,3 2,3 2,3 2,3 2,2 2,2z" Fill="#FFB8B8B9" Height="4" Canvas.Left="0" Canvas.Top="0" Width="13"/>
|
|
||||||
</Border>
|
|
||||||
</ControlTemplate>
|
|
||||||
</Setter.Value>
|
|
||||||
</Setter>
|
|
||||||
<Style.Triggers>
|
|
||||||
<Trigger Property="IsMouseOver" Value="True">
|
|
||||||
<Setter Property="Background" Value="#FF474D51"/>
|
|
||||||
</Trigger>
|
|
||||||
<Trigger Property="IsPressed" Value="True">
|
|
||||||
<Setter Property="Background" Value="#FF3D4347"/>
|
|
||||||
</Trigger>
|
|
||||||
</Style.Triggers>
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<!--Close Button-->
|
|
||||||
<Style x:Key="TiTleBarCloseButton" TargetType="{x:Type Button}">
|
|
||||||
<Setter Property="Background" Value="Transparent"/>
|
|
||||||
<Setter Property="Focusable" Value="False" />
|
|
||||||
<Setter Property="Template">
|
|
||||||
<Setter.Value>
|
|
||||||
<ControlTemplate TargetType="{x:Type Button}">
|
|
||||||
<Border Background="{TemplateBinding Background}">
|
|
||||||
<Path Data="F1M2,2C2,2,2.25,2,2.5,2L2.999,2 3,2 3,2.001 3.221,2.222C3.652,2.653,4.66,3.661,5.847,4.848L6.999,6 8.152,4.848C9.734,3.266,10.999,2,10.999,2L11,2.001 11,2C11,2 12,2 12,2 12,2 12,3 12,3 12,3 10.734,4.266 9.152,5.848L8,7 9.152,8.152C10.734,9.734 12,11 12,11 12,11 12,12 12,12 12,12 11,12 11,12L11,11.999 10.999,12C10.999,12,9.733,10.734,8.151,9.152L6.999,8 5.847,9.152C4.66,10.339,3.652,11.347,3.221,11.778L3,11.999 3,12 2.999,12C3,12 2,12 2,12 2,12 2,11 2,11 2,11 3.265,9.734 4.847,8.152L5.999,7 4.847,5.848C3.265,4.266,1.999,3,1.999,3L2,2.999 2,2.844C2,2.562,2,2,2,2z"
|
|
||||||
Fill="#FFB8B8B9" Height="13" Canvas.Left="0" Canvas.Top="0" Width="13"/>
|
|
||||||
</Border>
|
|
||||||
</ControlTemplate>
|
|
||||||
</Setter.Value>
|
|
||||||
</Setter>
|
|
||||||
<Style.Triggers>
|
|
||||||
<Trigger Property="IsMouseOver" Value="True">
|
|
||||||
<Setter Property="Background" Value="#FFF06251"/>
|
|
||||||
</Trigger>
|
|
||||||
<Trigger Property="IsPressed" Value="True">
|
|
||||||
<Setter Property="Background" Value="#FFED3F2B"/>
|
|
||||||
</Trigger>
|
|
||||||
</Style.Triggers>
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<Style x:Key="SettingButtonStyle" TargetType="ToggleButton">
|
|
||||||
<Setter Property="SnapsToDevicePixels" Value="True" />
|
|
||||||
<Setter Property="Focusable" Value="False"/>
|
|
||||||
<Setter Property="Height" Value="22" />
|
|
||||||
<Setter Property="Width" Value="22" />
|
|
||||||
<Setter Property="Template">
|
|
||||||
<Setter.Value>
|
|
||||||
<ControlTemplate TargetType="ToggleButton">
|
|
||||||
<Border x:Name="border" Padding="{TemplateBinding Padding}">
|
|
||||||
<Viewbox HorizontalAlignment="Center">
|
|
||||||
<Image Grid.Column="0" x:Name="img" Stretch="Fill" Source="{DynamicResource Images.OptionsMenu.Setting.Normal}" />
|
|
||||||
</Viewbox>
|
|
||||||
</Border>
|
|
||||||
|
|
||||||
<ControlTemplate.Triggers>
|
|
||||||
<Trigger Property="IsMouseOver" Value="True">
|
|
||||||
<Setter TargetName="border" Property="Background" Value="{DynamicResource Colors.Images.OptionsMenu.Setting.Background.MouseOver}" />
|
|
||||||
<Setter TargetName="img" Property="Source" Value="{DynamicResource Images.OptionsMenu.Setting.Pressed}"/>
|
|
||||||
</Trigger>
|
|
||||||
<Trigger Property="IsPressed" Value="True">
|
|
||||||
<Setter TargetName="border" Property="Background" Value="{DynamicResource Colors.Images.OptionsMenu.Setting.Background.MousePressed}"/>
|
|
||||||
<Setter TargetName="img" Property="Source" Value="{DynamicResource Images.OptionsMenu.Setting.Pressed}"/>
|
|
||||||
</Trigger>
|
|
||||||
<Trigger Property="IsChecked" Value="True">
|
|
||||||
<Setter TargetName="border" Property="Background" Value="{DynamicResource Colors.Images.OptionsMenu.Setting.Background.MousePressed}"/>
|
|
||||||
<Setter TargetName="img" Property="Source" Value="{DynamicResource Images.OptionsMenu.Setting.Pressed}"/>
|
|
||||||
</Trigger>
|
|
||||||
<Trigger Property="IsEnabled" Value="False">
|
|
||||||
<Setter Property="Opacity" Value="0.3" />
|
|
||||||
</Trigger>
|
|
||||||
</ControlTemplate.Triggers>
|
|
||||||
</ControlTemplate>
|
|
||||||
</Setter.Value>
|
|
||||||
</Setter>
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<Style x:Key="DataGridEditButtonStyle" TargetType="Button">
|
|
||||||
<Setter Property="BorderBrush" Value="Transparent"/>
|
|
||||||
<Setter Property="BorderThickness" Value="0"/>
|
|
||||||
<Setter Property="VerticalAlignment" Value="Bottom"/>
|
|
||||||
<Setter Property="Width" Value="56"/>
|
|
||||||
<Setter Property="Height" Value="20"/>
|
|
||||||
<Setter Property="Margin" Value="3 0"/>
|
|
||||||
<Setter Property="Background" Value="{DynamicResource Colors.DataGridButton.Background.Normal}"/>
|
|
||||||
<Setter Property="Foreground" Value="{DynamicResource Colors.DataGridButton.Foreground.Normal}"/>
|
|
||||||
<Setter Property="Template">
|
|
||||||
<Setter.Value>
|
|
||||||
<ControlTemplate TargetType="Button">
|
|
||||||
<Border CornerRadius="10" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
|
|
||||||
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Content="{TemplateBinding Content}"/>
|
|
||||||
</Border>
|
|
||||||
<ControlTemplate.Triggers>
|
|
||||||
<Trigger Property="IsMouseOver" Value="True">
|
|
||||||
<Setter Property="Background" Value="{DynamicResource Colors.DataGridButton.Background.MouseOver}"/>
|
|
||||||
<Setter Property="Foreground" Value="{DynamicResource Colors.DataGridButton.Foreground.MouseOver}"/>
|
|
||||||
</Trigger>
|
|
||||||
<Trigger Property="IsPressed" Value="True">
|
|
||||||
<Setter Property="Background" Value="{DynamicResource Colors.DataGridButton.Background.Pressed}"/>
|
|
||||||
<Setter Property="Foreground" Value="{DynamicResource Colors.DataGridButton.Foreground.Pressed}"/>
|
|
||||||
</Trigger>
|
|
||||||
<Trigger Property="IsEnabled" Value="False">
|
|
||||||
<Setter Property="Opacity" Value="0.3" />
|
|
||||||
</Trigger>
|
|
||||||
</ControlTemplate.Triggers>
|
|
||||||
</ControlTemplate>
|
|
||||||
</Setter.Value>
|
|
||||||
</Setter>
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
</ResourceDictionary>
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
using CommunityToolkit.Mvvm.Input;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using WPFBeginner.Services;
|
|
||||||
|
|
||||||
namespace WPFBeginner.ViewModels
|
|
||||||
{
|
|
||||||
public partial class LoginWindowViewModel : ObservableObject
|
|
||||||
{
|
|
||||||
[ObservableProperty]
|
|
||||||
private string user;
|
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
private string password;
|
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
private string message;
|
|
||||||
|
|
||||||
public ICommand LoginClickCommand => new RelayCommand<Window>((window) =>
|
|
||||||
{
|
|
||||||
if (CheckID() && CheckPassword())
|
|
||||||
window.DialogResult = true;
|
|
||||||
else
|
|
||||||
Message = ResourceExplorer.GetStringResource("Cultures.LoginWindow.ErrorMessage.InvalidUser");
|
|
||||||
});
|
|
||||||
|
|
||||||
public ICommand CloseClickCommand => new RelayCommand<Window>((window) =>
|
|
||||||
{
|
|
||||||
window.DialogResult = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
private bool CheckID() => user?.Equals(App.Config.Login.User, StringComparison.OrdinalIgnoreCase) ?? false;
|
|
||||||
|
|
||||||
private bool CheckPassword() => password?.Equals(App.Config.Login.Password, StringComparison.OrdinalIgnoreCase) ?? false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,217 +0,0 @@
|
|||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
using CommunityToolkit.Mvvm.Input;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using WPFBeginner.Models;
|
|
||||||
using WPFBeginner.Services;
|
|
||||||
using WPFBeginner.Views;
|
|
||||||
|
|
||||||
namespace WPFBeginner.ViewModels
|
|
||||||
{
|
|
||||||
public partial class MainWindowViewModel : ObservableRecipient
|
|
||||||
{
|
|
||||||
private ObservableCollection<Member> members;
|
|
||||||
public ObservableCollection<Member> Members
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (filterMemebers != null)
|
|
||||||
return filterMemebers;
|
|
||||||
|
|
||||||
return members;
|
|
||||||
}
|
|
||||||
set => SetProperty(ref members, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ObservableCollection<Member> filterMemebers;
|
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
private Member selectedMember;
|
|
||||||
|
|
||||||
private Member searchModel;
|
|
||||||
|
|
||||||
public string MemberName
|
|
||||||
{
|
|
||||||
get => searchModel?.Name;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (searchModel == null)
|
|
||||||
searchModel = new Member();
|
|
||||||
|
|
||||||
searchModel.Name = value;
|
|
||||||
OnPropertyChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Call
|
|
||||||
{
|
|
||||||
get => searchModel?.Call;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (searchModel == null)
|
|
||||||
searchModel = new Member();
|
|
||||||
|
|
||||||
searchModel.Call = value;
|
|
||||||
OnPropertyChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public string EmployeeNo
|
|
||||||
{
|
|
||||||
get => searchModel?.EmployeeNo;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (searchModel == null)
|
|
||||||
searchModel = new Member();
|
|
||||||
|
|
||||||
searchModel.EmployeeNo = value;
|
|
||||||
OnPropertyChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string EMail
|
|
||||||
{
|
|
||||||
get => searchModel.EMail;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (searchModel == null)
|
|
||||||
searchModel = new Member();
|
|
||||||
|
|
||||||
searchModel.EMail = value;
|
|
||||||
OnPropertyChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ICommand SearchClickCommand => new RelayCommand(() =>
|
|
||||||
{
|
|
||||||
var errorMessage = ValidateSearchValues();
|
|
||||||
if (errorMessage != null)
|
|
||||||
{
|
|
||||||
MessageBox.Show(errorMessage);
|
|
||||||
filterMemebers = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerable<Member> result = Members;
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(MemberName))
|
|
||||||
result = result.Where(i => i.Name?.Contains(MemberName) ?? false);
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(EMail))
|
|
||||||
result = result.Where(i => i.EMail?.Contains(EMail) ?? false);
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(Call))
|
|
||||||
result = result.Where(i => i.Call?.Contains(Call) ?? false);
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(EmployeeNo))
|
|
||||||
result = result.Where(i => i.EmployeeNo?.Contains(EmployeeNo) ?? false);
|
|
||||||
|
|
||||||
if (result == null)
|
|
||||||
filterMemebers = new ObservableCollection<Member>();
|
|
||||||
else
|
|
||||||
filterMemebers = new ObservableCollection<Member>(result);
|
|
||||||
|
|
||||||
OnPropertyChanged(nameof(Members));
|
|
||||||
});
|
|
||||||
|
|
||||||
public ICommand CloseCommand => new RelayCommand<Window>(window => window.Close());
|
|
||||||
|
|
||||||
public ICommand MinimizeCommand => new RelayCommand<Window>(window => window.WindowState = WindowState.Minimized);
|
|
||||||
|
|
||||||
public ICommand MaximizeCommad => new RelayCommand<Window>(window =>
|
|
||||||
{
|
|
||||||
switch (window.WindowState)
|
|
||||||
{
|
|
||||||
case WindowState.Maximized:
|
|
||||||
window.WindowState = WindowState.Normal;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WindowState.Normal:
|
|
||||||
window.WindowState = WindowState.Maximized;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
public bool IsKorean => App.Config.Language.Equals("ko-KR", StringComparison.OrdinalIgnoreCase);
|
|
||||||
public bool IsEnglish => App.Config.Language.Equals("en-US", StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
|
|
||||||
public ICommand LangueChangeCommand => new RelayCommand<string>(code =>
|
|
||||||
{
|
|
||||||
App.Config.Language = code;
|
|
||||||
OnPropertyChanged(nameof(IsKorean));
|
|
||||||
OnPropertyChanged(nameof(IsEnglish));
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public bool IsDefaultTheme => App.Config.Theme.Equals("DefaultTheme", StringComparison.OrdinalIgnoreCase);
|
|
||||||
public bool IsLightTheme => App.Config.Theme.Equals("LightTheme", StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
public ICommand ThemeChangeCommand => new RelayCommand<string>(code =>
|
|
||||||
{
|
|
||||||
App.Config.Theme = code;
|
|
||||||
OnPropertyChanged(nameof(IsDefaultTheme));
|
|
||||||
OnPropertyChanged(nameof(IsLightTheme));
|
|
||||||
});
|
|
||||||
|
|
||||||
private string ValidateSearchValues()
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(MemberName)
|
|
||||||
&& string.IsNullOrWhiteSpace(EmployeeNo)
|
|
||||||
&& string.IsNullOrWhiteSpace(Call)
|
|
||||||
&& string.IsNullOrWhiteSpace(EMail))
|
|
||||||
return ResourceExplorer.GetStringResource("Cultures.MainWindow.ErrorMessage.SearchConditionEmpty");
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ICommand DeleteClickCommand => new RelayCommand(() =>
|
|
||||||
{
|
|
||||||
if (SelectedMember == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Members.Remove(SelectedMember);
|
|
||||||
});
|
|
||||||
|
|
||||||
public ICommand InitClickCommand => new RelayCommand(() =>
|
|
||||||
{
|
|
||||||
filterMemebers = null;
|
|
||||||
searchModel = new Member();
|
|
||||||
OnPropertyChanged(nameof(MemberName));
|
|
||||||
OnPropertyChanged(nameof(EmployeeNo));
|
|
||||||
OnPropertyChanged(nameof(EMail));
|
|
||||||
OnPropertyChanged(nameof(Call));
|
|
||||||
OnPropertyChanged(nameof(Members));
|
|
||||||
});
|
|
||||||
|
|
||||||
public ICommand AddClickCommand => new RelayCommand<Window>((parentWindow) =>
|
|
||||||
{
|
|
||||||
var registDialog = new RegistMemberWindow();
|
|
||||||
registDialog.Owner = parentWindow;
|
|
||||||
var result = registDialog.ShowDialog();
|
|
||||||
if (result == true)
|
|
||||||
{
|
|
||||||
var dx = registDialog.DataContext as RegistMemberWindowViewModel;
|
|
||||||
if (dx == null)
|
|
||||||
return;
|
|
||||||
Members.Add(Member.Create(dx.MemberName, dx.Call, dx.Email, dx.EmployeeNo));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
public MainWindowViewModel()
|
|
||||||
{
|
|
||||||
CreateDefaultMember();
|
|
||||||
searchModel = new Member();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateDefaultMember()
|
|
||||||
{
|
|
||||||
members = new ObservableCollection<Member>();
|
|
||||||
foreach (var member in App.Config.Members)
|
|
||||||
members.Add(Member.Create(member.Name, member.Call, member.EMail, member.EmployeeNo));
|
|
||||||
OnPropertyChanged(nameof(Members));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
using CommunityToolkit.Mvvm.Input;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using WPFBeginner.Services;
|
|
||||||
|
|
||||||
namespace WPFBeginner.ViewModels
|
|
||||||
{
|
|
||||||
public partial class RegistMemberWindowViewModel : ObservableRecipient
|
|
||||||
{
|
|
||||||
[ObservableProperty]
|
|
||||||
private string memberName;
|
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
private string call;
|
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
private string employeeNo;
|
|
||||||
|
|
||||||
[ObservableProperty]
|
|
||||||
private string email;
|
|
||||||
|
|
||||||
public ICommand RegistClickCommand => new RelayCommand<Window>((window) =>
|
|
||||||
{
|
|
||||||
var result = Validate();
|
|
||||||
if (result != null)
|
|
||||||
MessageBox.Show(result);
|
|
||||||
else
|
|
||||||
window.DialogResult = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
public ICommand CancelClickCommand => new RelayCommand<Window>((window) =>
|
|
||||||
{
|
|
||||||
window.DialogResult = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private string Validate()
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(MemberName) || string.IsNullOrWhiteSpace(EmployeeNo))
|
|
||||||
return ResourceExplorer.GetStringResource("Cultures.RegistMemberWindow.ErrorMessage.FillMustValue");
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
<Window x:Class="WPFBeginner.Views.LoginWindow"
|
|
||||||
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:vm="clr-namespace:WPFBeginner.ViewModels"
|
|
||||||
xmlns:sv="clr-namespace:WPFBeginner.Services"
|
|
||||||
Background="Transparent" AllowsTransparency="True"
|
|
||||||
WindowStyle="None" Name="root" WindowStartupLocation="CenterScreen"
|
|
||||||
mc:Ignorable="d" Height="436" Width="720">
|
|
||||||
|
|
||||||
<Window.DataContext>
|
|
||||||
<vm:LoginWindowViewModel/>
|
|
||||||
</Window.DataContext>
|
|
||||||
|
|
||||||
<WindowChrome.WindowChrome>
|
|
||||||
<WindowChrome CaptionHeight="{Binding ElementName=root, Path=ActualHeight}" />
|
|
||||||
</WindowChrome.WindowChrome>
|
|
||||||
|
|
||||||
<Window.Resources>
|
|
||||||
<Style x:Key="LoginButtonStyle" TargetType="Button">
|
|
||||||
<Setter Property="Template" >
|
|
||||||
<Setter.Value>
|
|
||||||
<ControlTemplate TargetType="Button">
|
|
||||||
<Border CornerRadius="15" Background="{TemplateBinding Background}">
|
|
||||||
<Label HorizontalAlignment="Center" VerticalAlignment="Center"
|
|
||||||
Foreground="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Foreground}"
|
|
||||||
Content="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Content}"/>
|
|
||||||
</Border>
|
|
||||||
</ControlTemplate>
|
|
||||||
</Setter.Value>
|
|
||||||
</Setter>
|
|
||||||
</Style>
|
|
||||||
</Window.Resources>
|
|
||||||
|
|
||||||
<Window.Clip>
|
|
||||||
<RectangleGeometry Rect="0,0,720,436" RadiusX="15" RadiusY="15"/>
|
|
||||||
</Window.Clip>
|
|
||||||
|
|
||||||
<Border Background="Transparent">
|
|
||||||
<Grid>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="36"/>
|
|
||||||
<RowDefinition Height="*"/>
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<Image Source="/Resources/Images/bg_login.jpeg" Stretch="Fill" Grid.RowSpan="2"/>
|
|
||||||
<Grid Grid.Row="0">
|
|
||||||
<StackPanel Orientation="Horizontal" Margin="0,0,17,0" Height="29" HorizontalAlignment="Right" VerticalAlignment="Top" WindowChrome.IsHitTestVisibleInChrome="True">
|
|
||||||
<Button Width="46" Height="29" Style="{DynamicResource TiTleBarCloseButton}" Command="{Binding CloseClickCommand}" CommandParameter="{Binding ElementName=root}"
|
|
||||||
IsTabStop="True" TabIndex="4"/>
|
|
||||||
</StackPanel>
|
|
||||||
</Grid>
|
|
||||||
<Grid Grid.Row="1">
|
|
||||||
<Label Content="WPF toy project" FontFamily="Noto Sans CJK KR Medium" FontSize="48" Foreground="White" Margin="0,93,0,0" Width="Auto" Height="Auto" HorizontalAlignment="Center" VerticalAlignment="Top"/>
|
|
||||||
<Label Content="For beginner" FontFamily="Noto Sans CJK KR Medium" FontSize="24" Foreground="White" Margin="389,60,0,0" Width="Auto" Height="Auto" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
|
||||||
<Border CornerRadius="5" Margin="150,179,150,32" Background="#4CFFFFFF" WindowChrome.IsHitTestVisibleInChrome="True">
|
|
||||||
<Grid FocusManager.FocusedElement="{Binding ElementName=TB_User}">
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="*"/>
|
|
||||||
<RowDefinition Height="*"/>
|
|
||||||
<RowDefinition Height="*"/>
|
|
||||||
<RowDefinition Height="1.2*"/>
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="40"/>
|
|
||||||
<ColumnDefinition Width="*"/>
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Label Grid.ColumnSpan="2" Content="{DynamicResource Cultures.LoginWindow.Inform}" Margin="15,0" FontSize="24" HorizontalAlignment="Left" VerticalAlignment="Center" FontWeight="Bold" FontFamily="Noto Sans CJK KR Medium" Foreground="Black" />
|
|
||||||
<Image Grid.Row="1" Grid.Column="0" Source="/Resources/Images/ico_user.png" Margin="10"/>
|
|
||||||
<TextBox Grid.Row="1" Grid.Column="1" Name="TB_User" Text="{Binding User}" Margin="5,5,15,0" FontSize="14"
|
|
||||||
Background="#7FFFFFFF" VerticalContentAlignment="Center" Padding="10,0,0,0"
|
|
||||||
IsTabStop="True" TabIndex="1" Focusable="True" sv:EnterKeyTraversal.IsEnabled="True"/>
|
|
||||||
<Image Grid.Row="2" Grid.Column="0" Source="/Resources/Images/ico_pw.png" Margin="10"/>
|
|
||||||
<PasswordBox Grid.Row="2" Grid.Column="1" sv:PasswordBoxAssistant.EnableBindingPassword="True" sv:EnterKeyTraversal.IsEnabled="True"
|
|
||||||
sv:PasswordBoxAssistant.BoundPassword="{Binding Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="5,5,15,0"
|
|
||||||
FontSize="14" Background="#7FFFFFFF" VerticalContentAlignment="Center" Padding="10,0,0,0" IsTabStop="True" TabIndex="2"/>
|
|
||||||
<Grid Grid.Row="3" Grid.ColumnSpan="2">
|
|
||||||
<Button Style="{StaticResource LoginButtonStyle}" Content="{DynamicResource Cultures.LoginWindow.LoginButtonText}" Margin="100,5" Background="#FFFF7575" FontSize="14" Foreground="White" FontWeight="Bold"
|
|
||||||
Command="{Binding LoginClickCommand}" CommandParameter="{Binding ElementName=root}" IsTabStop="True" TabIndex="3"/>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Border>
|
|
||||||
|
|
||||||
<Label Content="{Binding Message}" FontFamily="Noto Sans CJK KR Medium" FontSize="11" Foreground="Yellow"
|
|
||||||
Margin="159,369,0,0" Width="Auto" Height="Auto" HorizontalAlignment="Left" VerticalAlignment="Top" d:Content="ddd"/>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Border>
|
|
||||||
</Window>
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
using System.Windows;
|
|
||||||
|
|
||||||
namespace WPFBeginner.Views
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// LoginWindow.xaml에 대한 상호 작용 논리
|
|
||||||
/// </summary>
|
|
||||||
public partial class LoginWindow : Window
|
|
||||||
{
|
|
||||||
public LoginWindow()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,172 +0,0 @@
|
|||||||
<Window x:Class="WPFBeginner.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:uc="clr-namespace:WPFBeginner.Controls"
|
|
||||||
WindowStyle="None" ResizeMode="CanResize" Name="root"
|
|
||||||
mc:Ignorable="d" Title="MainWindow" Height="500" Width="400" Padding="20">
|
|
||||||
|
|
||||||
<WindowChrome.WindowChrome>
|
|
||||||
<WindowChrome CaptionHeight="{Binding ElementName=titleBar, Path=ActualHeight}" ResizeBorderThickness="0 5 0 5"/>
|
|
||||||
</WindowChrome.WindowChrome>
|
|
||||||
|
|
||||||
<Window.DataContext>
|
|
||||||
<Binding Source="{StaticResource ViewModelLocator}" Path="MainWindowViewModel"/>
|
|
||||||
</Window.DataContext>
|
|
||||||
|
|
||||||
<Window.Resources>
|
|
||||||
|
|
||||||
<Style x:Key="SearchButton" TargetType="Button">
|
|
||||||
<Setter Property="Background" Value="{DynamicResource Colors.SearchButton.Background.Normal}"/>
|
|
||||||
<Setter Property="BorderBrush" Value="{DynamicResource Colors.SearchButton.BorderBrush.Normal}"/>
|
|
||||||
<Setter Property="Foreground" Value="{DynamicResource Colors.SearchButton.Foreground.Normal}"/>
|
|
||||||
<Setter Property="BorderThickness" Value="1"/>
|
|
||||||
<Setter Property="Template">
|
|
||||||
<Setter.Value>
|
|
||||||
<ControlTemplate TargetType="Button">
|
|
||||||
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
|
|
||||||
<ContentControl Content="{TemplateBinding Content}"/>
|
|
||||||
</Border>
|
|
||||||
<ControlTemplate.Triggers>
|
|
||||||
<Trigger Property="IsMouseOver" Value="True">
|
|
||||||
<Setter Property="Background" Value="{DynamicResource Colors.SearchButton.Background.MouseOver}"/>
|
|
||||||
<Setter Property="BorderBrush" Value="{DynamicResource Colors.SearchButton.BorderBrush.MouseOver}"/>
|
|
||||||
<Setter Property="Foreground" Value="{DynamicResource Colors.SearchButton.Foreground.MouseOver}"/>
|
|
||||||
</Trigger>
|
|
||||||
<Trigger Property="IsPressed" Value="True">
|
|
||||||
<Setter Property="Background" Value="{DynamicResource Colors.SearchButton.Background.MousePressed}"/>
|
|
||||||
<Setter Property="BorderBrush" Value="{DynamicResource Colors.SearchButton.BorderBrush.MousePressed}"/>
|
|
||||||
<Setter Property="Foreground" Value="{DynamicResource Colors.SearchButton.Foreground.MousePressed}"/>
|
|
||||||
</Trigger>
|
|
||||||
</ControlTemplate.Triggers>
|
|
||||||
</ControlTemplate>
|
|
||||||
</Setter.Value>
|
|
||||||
</Setter>
|
|
||||||
</Style>
|
|
||||||
</Window.Resources>
|
|
||||||
|
|
||||||
<Grid>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="40"/>
|
|
||||||
<RowDefinition Height="130"/>
|
|
||||||
<RowDefinition Height="*"/>
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<!--Title Bar-->
|
|
||||||
<Grid x:Name="titleBar" Background="{DynamicResource Colors.TitleBar.Title.Background}" >
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="*"/>
|
|
||||||
<ColumnDefinition Width="Auto"/>
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Label Content="{DynamicResource Cultures.MainWindow.Title}" Foreground="{DynamicResource Colors.TitleBar.Title.Foreground}"
|
|
||||||
FontSize="14" FontFamily="NanumSquareOTF_ac Bold" VerticalContentAlignment="Center" Padding="10 0"/>
|
|
||||||
<Grid Grid.Column="2">
|
|
||||||
<StackPanel Orientation="Horizontal" WindowChrome.IsHitTestVisibleInChrome="True" VerticalAlignment="Top">
|
|
||||||
<ToggleButton Width="22" Height="22" Style="{DynamicResource SettingButtonStyle}" Name="bt_settings"/>
|
|
||||||
<Button Width="39" Height="27" Style="{DynamicResource TiTleBarMinimizeButton}" Command="{Binding MinimizeCommand}" CommandParameter="{Binding ElementName=root}"/>
|
|
||||||
<Button Width="39" Height="27" Style="{DynamicResource TiTleBarMaximizeButton}" Command="{Binding MaximizeCommad}" CommandParameter="{Binding ElementName=root}"/>
|
|
||||||
<Button Width="39" Height="27" Style="{DynamicResource TiTleBarCloseButton}" Command="{Binding CloseCommand}" CommandParameter="{Binding ElementName=root}"/>
|
|
||||||
</StackPanel>
|
|
||||||
<Popup PlacementTarget="{Binding ElementName=bt_settings}" Placement="Bottom" IsOpen="{Binding ElementName=bt_settings, Path=IsChecked}" StaysOpen="False">
|
|
||||||
<Border Background="{DynamicResource Colors.SettingPopup.Background}" BorderThickness="1" BorderBrush="{DynamicResource Colors.SettingPopup.BorderBrush}" >
|
|
||||||
<StackPanel Orientation="Vertical" Width="100">
|
|
||||||
<Grid Margin="5">
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="*"/>
|
|
||||||
<RowDefinition Height="5"/>
|
|
||||||
<RowDefinition Height="*"/>
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<StackPanel>
|
|
||||||
<RadioButton Content="한글판" Foreground="{DynamicResource Colors.SettingPopup.Foreground}"
|
|
||||||
GroupName="Cultures" IsChecked="{Binding IsKorean, Mode=OneWay}" Command="{Binding LangueChangeCommand}" CommandParameter="ko-KR"/>
|
|
||||||
<RadioButton Content="English" Foreground="{DynamicResource Colors.SettingPopup.Foreground}"
|
|
||||||
GroupName="Cultures" IsChecked="{Binding IsEnglish, Mode=OneWay}" Command="{Binding LangueChangeCommand}" CommandParameter="en-US"/>
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<StackPanel Grid.Row="2">
|
|
||||||
<RadioButton Content="Default" Foreground="{DynamicResource Colors.SettingPopup.Foreground}" GroupName="Themes"
|
|
||||||
IsChecked="{Binding IsDefaultTheme, Mode=OneWay}" Command="{Binding ThemeChangeCommand}" CommandParameter="DefaultTheme"/>
|
|
||||||
<RadioButton Content="Light" Foreground="{DynamicResource Colors.SettingPopup.Foreground}" GroupName="Themes"
|
|
||||||
IsChecked="{Binding IsLightTheme, Mode=OneWay}" Command="{Binding ThemeChangeCommand}" CommandParameter="LightTheme"/>
|
|
||||||
</StackPanel>
|
|
||||||
</Grid>
|
|
||||||
</StackPanel>
|
|
||||||
</Border>
|
|
||||||
</Popup>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
<Border HorizontalAlignment="Stretch" VerticalAlignment="Bottom" BorderThickness="0.5" BorderBrush="{DynamicResource Colors.Section.HorizontalSeperator}"/>
|
|
||||||
|
|
||||||
<!-- Filter Box -->
|
|
||||||
<Border Grid.Row="1" Padding="0 10" HorizontalAlignment="Right" Width="400" Background="{DynamicResource Colors.Main.Background}">
|
|
||||||
<Grid HorizontalAlignment="Right" Width="400">
|
|
||||||
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="*"/>
|
|
||||||
<ColumnDefinition Width="Auto"/>
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
|
|
||||||
<uc:MemberInputPanel MemberName="{Binding MemberName}" Call="{Binding Call}"
|
|
||||||
EmployeeNo="{Binding EmployeeNo}" Email="{Binding Email}"/>
|
|
||||||
|
|
||||||
<Grid Grid.RowSpan="4" Grid.Column="1">
|
|
||||||
<Button Margin="3" HorizontalAlignment="Center" VerticalAlignment="Center" Padding="2" Style="{StaticResource SearchButton}"
|
|
||||||
Command="{Binding SearchClickCommand}">
|
|
||||||
<StackPanel VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
|
|
||||||
<Image Source="/Resources/Images/btn_search_001.png" Stretch="UniformToFill"/>
|
|
||||||
<Label Content="{DynamicResource Cultures.MainWindow.Button.Search}"
|
|
||||||
Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType=Button}}"
|
|
||||||
HorizontalAlignment="Center" FontFamily="Yu Gothic UI" FontWeight="Bold" FontSize="12" Margin="0" Padding="0"/>
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Border>
|
|
||||||
|
|
||||||
<Border Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" BorderThickness="0.5" BorderBrush="{DynamicResource Colors.Section.HorizontalSeperator}"/>
|
|
||||||
|
|
||||||
<!-- Search Result -->
|
|
||||||
<Grid Grid.Row="3" Background="{DynamicResource Colors.Main.Background}">
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="50"/>
|
|
||||||
<RowDefinition Height="*"/>
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<Grid>
|
|
||||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="10 5">
|
|
||||||
<Button Content="{DynamicResource Cultures.MainWindow.Button.Add}" Style="{DynamicResource DataGridEditButtonStyle}" Command="{Binding AddClickCommand}" CommandParameter="{Binding ElementName=root}"/>
|
|
||||||
<Button Content="{DynamicResource Cultures.MainWindow.Button.Delete}" Style="{DynamicResource DataGridEditButtonStyle}" Command="{Binding DeleteClickCommand}"/>
|
|
||||||
<Button Content="{DynamicResource Cultures.MainWindow.Button.Init}" Style="{DynamicResource DataGridEditButtonStyle}" Command="{Binding InitClickCommand}"/>
|
|
||||||
</StackPanel>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<DataGrid Grid.Row="1" Margin="5" ItemsSource="{Binding Members}" SelectedItem="{Binding SelectedMember}" AutoGenerateColumns="False" IsReadOnly="True">
|
|
||||||
<DataGrid.Columns>
|
|
||||||
<DataGridTextColumn Binding="{Binding Name}" Width="*">
|
|
||||||
<DataGridTextColumn.Header>
|
|
||||||
<TextBlock Text="{DynamicResource Cultures.MainWindow.DatagGid.Column.Name}" />
|
|
||||||
</DataGridTextColumn.Header>
|
|
||||||
</DataGridTextColumn>
|
|
||||||
<DataGridTextColumn Binding="{Binding Call}" Width="*">
|
|
||||||
<DataGridTextColumn.Header>
|
|
||||||
<TextBlock Text="{DynamicResource Cultures.MainWindow.DatagGid.Column.Call}" />
|
|
||||||
</DataGridTextColumn.Header>
|
|
||||||
</DataGridTextColumn>
|
|
||||||
<DataGridTextColumn Binding="{Binding EmployeeNo}" Width="*">
|
|
||||||
<DataGridTextColumn.Header>
|
|
||||||
<TextBlock Text="{DynamicResource Cultures.MainWindow.DatagGid.Column.No}" />
|
|
||||||
</DataGridTextColumn.Header>
|
|
||||||
</DataGridTextColumn>
|
|
||||||
<DataGridTextColumn Binding="{Binding EMail}" Width="*">
|
|
||||||
<DataGridTextColumn.Header>
|
|
||||||
<TextBlock Text="{DynamicResource Cultures.MainWindow.DatagGid.Column.Email}" />
|
|
||||||
</DataGridTextColumn.Header>
|
|
||||||
</DataGridTextColumn>
|
|
||||||
</DataGrid.Columns>
|
|
||||||
</DataGrid>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
</Grid>
|
|
||||||
</Window>
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
using System.Windows;
|
|
||||||
|
|
||||||
namespace WPFBeginner
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Interaction logic for MainWindow.xaml
|
|
||||||
/// </summary>
|
|
||||||
public partial class MainWindow : Window
|
|
||||||
{
|
|
||||||
public MainWindow()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
<Window x:Class="WPFBeginner.Views.RegistMemberWindow"
|
|
||||||
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:uc="clr-namespace:WPFBeginner.Controls"
|
|
||||||
xmlns:bh="clr-namespace:WPFBeginner.Behaviors"
|
|
||||||
WindowStyle="SingleBorderWindow"
|
|
||||||
xmlns:vm ="clr-namespace:WPFBeginner.ViewModels"
|
|
||||||
mc:Ignorable="d" WindowStartupLocation="CenterOwner" Name="root"
|
|
||||||
Title="" SizeToContent="WidthAndHeight" MinWidth="350" MinHeight="200" d:DesignHeight="200" d:DesignWidth="200"
|
|
||||||
bh:WindowBehavior.HideCloseButton="True">
|
|
||||||
|
|
||||||
<Window.DataContext>
|
|
||||||
<vm:RegistMemberWindowViewModel />
|
|
||||||
</Window.DataContext>
|
|
||||||
|
|
||||||
<Border Background="{DynamicResource Colors.Main.Background}" Padding="5">
|
|
||||||
<Grid>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="*"/>
|
|
||||||
<RowDefinition Height="30"/>
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<uc:MemberInputPanel x:Name="memberPanel"
|
|
||||||
MemberName="{Binding MemberName}"
|
|
||||||
Call="{Binding Call}"
|
|
||||||
EmployeeNo="{Binding EmployeeNo}"
|
|
||||||
Email="{Binding Email}"/>
|
|
||||||
|
|
||||||
<Grid Grid.Row="1">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="*"/>
|
|
||||||
<ColumnDefinition Width="10"/>
|
|
||||||
<ColumnDefinition Width="*"/>
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Button Content="{DynamicResource Cultures.RegistMemberWindow.RegistButton}" HorizontalAlignment="Stretch" Width="Auto"
|
|
||||||
Command="{Binding RegistClickCommand}" CommandParameter="{Binding ElementName=root}"/>
|
|
||||||
<Button Grid.Column="2" Content="{DynamicResource Cultures.RegistMemberWindow.CancelButton}" HorizontalAlignment="Stretch" Width="Auto"
|
|
||||||
Command="{Binding CancelClickCommand}" CommandParameter="{Binding ElementName=root}"/>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
</Border>
|
|
||||||
</Window>
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
using System.Windows;
|
|
||||||
|
|
||||||
namespace WPFBeginner.Views
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// RegistMemberWindow.xaml에 대한 상호 작용 논리
|
|
||||||
/// </summary>
|
|
||||||
public partial class RegistMemberWindow : Window
|
|
||||||
{
|
|
||||||
public RegistMemberWindow()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>WinExe</OutputType>
|
|
||||||
<TargetFramework>net8.0-windows</TargetFramework>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<UseWPF>true</UseWPF>
|
|
||||||
<StartupObject>WPFBeginner.App</StartupObject>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Remove="appsettings.json" />
|
|
||||||
<None Remove="Resources\Images\bg_login.jpeg" />
|
|
||||||
<None Remove="Resources\Images\btn_search_001.png" />
|
|
||||||
<None Remove="Resources\Images\ico_pw.png" />
|
|
||||||
<None Remove="Resources\Images\ico_user.png" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Content Include="appsettings.json">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Resource Include="Resources\Images\bg_login.jpeg" />
|
|
||||||
<Resource Include="Resources\Images\btn_search_001.png" />
|
|
||||||
<Resource Include="Resources\Images\ico_pw.png" />
|
|
||||||
<Resource Include="Resources\Images\ico_user.png" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ApplicationDefinition Update="App.xaml">
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
|
||||||
</ApplicationDefinition>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio Version 17
|
|
||||||
VisualStudioVersion = 17.9.34607.119
|
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WPFBeginner", "WPFBeginner\WPFBeginner.csproj", "{8A5A2302-7A11-434B-8C98-D586BDC85E4C}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Any CPU = Debug|Any CPU
|
|
||||||
Release|Any CPU = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{8A5A2302-7A11-434B-8C98-D586BDC85E4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{8A5A2302-7A11-434B-8C98-D586BDC85E4C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{8A5A2302-7A11-434B-8C98-D586BDC85E4C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{8A5A2302-7A11-434B-8C98-D586BDC85E4C}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
SolutionGuid = {65B27DF8-6AA9-4BC1-964B-51069FA5B003}
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||