# c-entron.NET WPF GUI - Architecture & Reuse Patterns

## CRITICAL VIEWMODEL REUSE PATTERNS

### TIER 1: EXTREME REUSE (8+ Contexts)

#### TicketListViewModel [MOST REUSED]
**Reuse Locations**:
1. Helpdesk.TicketList.TicketListView (PRIMARY)
   - Path: `Modules/Helpdesk/TicketList/TicketListView.xaml`
   - Full ticket management interface with all filters

2. Helpdesk.TicketList.TicketListWithDialogView
   - Path: `Modules/Helpdesk/TicketList/TicketListWithDialogView.xaml`
   - Dialog wrapper for ticket selection

3. Helpdesk.TicketList.TicketListWithRibbonView
   - Path: `Modules/Helpdesk/TicketList/TicketListWithRibbonView.xaml`
   - Variant with ribbon toolbar

4. Finances.AccountManagement.AccountManagementView [NESTED TAB]
   - Path: `Modules/Finances/AccountManagement/AccountManagementView.xaml`
   - Embedded as "Tickets" tab in customer account view
   - Shows all tickets related to selected customer

5. Sales.CampaignAnalysis
   - Used to display customer activity/ticket history within campaign context

6. Warehousing.Commissioning
   - References tickets for commissioning order tracking

7. Dashboard.HelpdeskDashboardContainerView
   - Statistics aggregation of tickets

8. Reports Module
   - Ticket analytics and reporting views

9. MyCentron Module
   - Personal task list (filtered ticket view)

10. Multiple Dialog Contexts
    - HelpdeskConnectionNumberSelectionView
    - Ticket preview dialogs
    - Batch operations dialogs

**Key Design Pattern**: Context-aware filtering
- When instantiated in AccountManagement: Shows only tickets for selected customer
- When instantiated in Helpdesk: Shows all accessible tickets
- When instantiated in Reports: Shows filtered/aggregated ticket data
- Same ViewModel, different visual contexts and filter presets

**Initialization Pattern**:
```csharp
// In AccountManagementViewModel constructor:
this.TicketListViewModel = new TicketListViewModel();
// Then bound in XAML: <ticketList1:TicketListView DataContext="{Binding TicketListViewModel}" />
```

---

### TIER 2: HIGH REUSE (4-7 Contexts)

#### ReceiptsOverviewViewModel
**Reuse Locations**:
1. Finances.AccountManagement (PRIMARY)
   - Shows all receipts for selected customer

2. Finances.Receipts.ReceiptsModule
   - Standalone receipt management view

3. Finances.Invoicing
   - Invoice-specific receipt view

4. CRM.CustomerDetail
   - Customer transaction history tab

5. Reports.TransactionReports
   - Receipt analytics

**Pattern**: Same grid-based display, different filter contexts

---

#### AccountSalesStatisticViewModel
**Reuse Locations**:
1. Finances.AccountManagement.Dashboard (PRIMARY)
   - Main statistics view with ChartControl

2. MyCentron.Dashboard
   - Personal sales metrics

3. Sales.Dashboard
   - Department sales metrics

4. Reports.AccountAnalysis
   - Detailed account analysis

---

#### Dashboard Container ViewModels (7 variations)
**Pattern**: Each specialized for single metric
1. HelpdeskDashboardContainerViewModel → Overall helpdesk KPIs
2. TicketStatusDashboardContainerViewModel → Status distribution
3. TicketPriorityDashboardContainerViewModel → Priority breakdown
4. TicketTypeDashboardContainerViewModel → Type distribution
5. TicketDueDateDashboardContainerViewModel → Due date analysis
6. TicketDatesDashboardContainerViewModel → Date range analysis
7. TicketRecordedTimeContainerViewModel → Time tracking metrics

**Reuse**: All 7 appear in multiple dashboard views throughout system

---

### TIER 3: MODERATE REUSE (2-3 Contexts)

#### AccountManagementViewModel
**Reuse Locations**:
1. Finances.AccountManagement (PRIMARY)
   - Main account/customer management view

2. CRM.AccountDetails
   - Detailed account information panels

3. Sales.OrderEntry
   - Customer selection and account validation

---

#### AuthenticationSettingsViewModel
**Reuse Locations**:
1. Administration.Connections (PRIMARY)

2. Administration.Settings
   - General authentication settings

---

### TIER 4: SINGLE-PURPOSE (1 Context Only)

#### Single-Use ViewModels
- CountryManagementViewModel (Administration.CountryManagement)
- ProductionOrderManagementViewModel (Production.ProductionOrder)
- ArticleManagementViewModel (primarily Warehousing, minimal dialog reuse)
- RightsManagementViewModel (Administration.RightsManagement)
- MailTemplatesModuleViewModel (Administration.MailTemplates)
- And many others...

**Percentage**: ~70% of ViewModels are single-purpose, ~30% are reused

---

## NESTED VIEWMODEL PATTERN

### AccountManagementViewModel Structure (5-level nesting)
```
AccountManagementViewModel (root - ViewModelBase)
├── ReceiptsOverviewViewModel (nested - INotifyPropertyChanged)
│   ├── ReceiptItemViewModel
│   └── ReceiptFilterViewModel
├── TicketListViewModel (REUSED - IViewModelWithLoading)
│   ├── HelpdeskListItemViewModel (collection items)
│   └── TicketListUISettingsViewModel
├── AccountSalesStatisticViewModel (nested - ViewModelBase)
│   ├── ChartDataViewModel
│   └── StatisticSeriesViewModel
├── BranchBookKeepingNumbersViewModel (nested)
│   └── BranchViewModel (collection items)
└── OrderProcessingContractViewModel (nested - per contract)
    └── ContractStatusViewModel
```

**Pattern Benefits**:
- Each nested ViewModel manages its own state
- Parent coordinates overall view layout
- Tab switching shows/hides child ViewModel content
- Simplifies testing (isolate ViewModel hierarchy)

**Parent Property Pattern**:
```csharp
private TicketListViewModel _ticketListViewModel;
public TicketListViewModel TicketListViewModel
{
    get { return this._ticketListViewModel; }
    set { this.SetProperty(ref this._ticketListViewModel, value, () => this.TicketListViewModel); }
}
```

---

## MASTER-DETAIL LAYOUT PATTERN (Standard Across 80% of Views)

### Typical Structure:
```xaml
<LayoutControl Orientation="Horizontal">
  <!-- LEFT PANEL: Fixed Width ~250-300px -->
  <LayoutItem Width="250" AllowHorizontalSizing="True">
    <GridControl ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}">
      <!-- Master list: Countries, Customers, Tickets, Articles, etc. -->
    </GridControl>
  </LayoutItem>

  <!-- RIGHT PANEL: Flex Width -->
  <LayoutGroup Width="*" Orientation="Vertical">
    <!-- Detail form with input controls -->
    <TextEdit Value="{Binding SelectedItem.Name}" />
    <ComboBox ItemsSource="{Binding Categories}" SelectedItem="{Binding SelectedCategory}" />
    <!-- More details... -->
  </LayoutGroup>
</LayoutControl>
```

### Usage Throughout:
- Administration.CountryManagement: Countries list (left) + Country properties (right)
- Finances.AccountManagement: Customers list (left) + Tabs (right)
- Helpdesk.TicketList: Tickets list (left) + Filters above (top)
- Warehousing.ArticleManagement: Articles list (left) + Article details (right)
- Production.ProductionOrder: Orders list (left) + Order details (right)

---

## RIBBON COMMAND PATTERN (150+ Views)

### Standard Ribbon Structure:
```xaml
<RibbonControl x:Name="RibbonControl">
  <RibbonDefaultPageCategory>
    <RibbonPage>
      <!-- GROUP 1: Data operations (Save, Print, Export) -->
      <RibbonPageGroup Caption="Daten">
        <BarButtonItem Command="{Binding SaveCommand}" 
                       Content="Speichern" 
                       Glyph="16x16/Save.png"
                       LargeGlyph="32x32/Save.png"
                       KeyGesture="Ctrl+S" />
        <BarButtonItem Command="{Binding PrintCommand}" Content="Drucken" />
        <BarButtonItem Command="{Binding ExportCommand}" Content="Exportieren" />
      </RibbonPageGroup>

      <!-- GROUP 2: Entity operations (New, Delete) -->
      <RibbonPageGroup Caption="Land">
        <BarButtonItem Command="{Binding NewCountryCommand}" Content="Neu" RibbonStyle="Large" />
        <BarButtonItem Command="{Binding DeactivateCountryCommand}" Content="Deaktivieren" />
      </RibbonPageGroup>

      <!-- GROUP 3: Special operations -->
      <RibbonPageGroup Caption="Sonder">
        <BarButtonItem Command="{Binding SpecialCommand}" Content="Besondere Aktion" />
      </RibbonPageGroup>
    </RibbonPage>
  </RibbonDefaultPageCategory>
</RibbonControl>
```

### Command Mapping:
- Save: UpdateCommand (Ctrl+S hotkey)
- New: CreateCommand with ItemType parameter
- Delete/Deactivate: SoftDeleteCommand (IsDeleted flag, not actual delete)
- Print: PrintCommand (uses DevExpress PrintTool)
- Export: ExportCommand (Excel, CSV, PDF)
- Special: Custom business logic commands

---

## OBSERVABLE COLLECTION PATTERN

### Standard Implementation:
```csharp
using CentronObservableCollection; // Custom collection type

private CentronObservableCollection<CountryViewModel> _countries;

public CentronObservableCollection<CountryViewModel> Countries
{
    get => this._countries;
    set => this.SetProperty(ref this._countries, value, nameof(this._countries));
}

// In constructor:
public CountryManagementViewModel()
{
    this.Countries = new CentronObservableCollection<CountryViewModel>();
    _ = this.GetCountries(); // Async load
}

public async Task GetCountries()
{
    var result = await ClassContainer.Instance
        .WithInstance((ICountryLogic logic) => logic.GetActiveCountries());
    
    if (result.IsSuccess)
    {
        this.Countries = new CentronObservableCollection<CountryViewModel>(
            result.Data.Select(c => new CountryViewModel(c))
        );
    }
}
```

### Variants:
- **CentronObservableCollection<T>**: Custom type with built-in change notifications
- **ObservableCollection<T>**: WPF standard (used for smaller collections)
- **IList<T>**: For internal caching without UI binding

---

## COMMAND IMPLEMENTATION PATTERNS

### DelegateCommand (Synchronous)
```csharp
public DelegateCommand NewCountryCommand { get; }

public CountryManagementViewModel()
{
    this.NewCountryCommand = new DelegateCommand(
        execute: this.AddNewCountry,
        canExecute: () => !this.IsLoading
    );
}

private void AddNewCountry()
{
    var newCountry = new CountryViewModel();
    this.Countries.Add(newCountry);
    this.SelectedCountry = newCountry;
}
```

### AsyncCommand (Asynchronous)
```csharp
public AsyncCommand UpdateCountryCommand { get; }
public AsyncCommand<int> DeleteCountryCommand { get; }

public CountryManagementViewModel()
{
    this.UpdateCountryCommand = new AsyncCommand(
        execute: this.UpdateCountry,
        canExecute: () => this.SelectedCountry != null && !this.IsLoading
    );
    
    this.DeleteCountryCommand = new AsyncCommand<int>(
        execute: (countryId) => this.DeleteCountry(countryId),
        canExecute: (countryId) => !this.IsLoading
    );
}

private async Task UpdateCountry()
{
    try
    {
        this.IsLoading = true;
        var result = await ClassContainer.Instance
            .WithInstance((ICountryLogic logic) => logic.UpdateCountry(this.SelectedCountry));
        
        if (result.IsSuccess)
        {
            // Refresh list
            await this.GetCountries();
        }
    }
    finally
    {
        this.IsLoading = false;
    }
}
```

---

## FILTER PATTERN (Most List Views)

### Filter Section Structure:
```xaml
<LayoutGroup x:Name="FilterLayoutGroup" IsCollapsible="True" Visibility="{Binding UISettings.ShowFilter}">
  <!-- Header with icons and clear button -->
  <LayoutGroup.HeaderTemplate>
    <DataTemplate>
      <StackPanel Orientation="Horizontal">
        <Image Source="{StaticResource FilterIcon}" />
        <TextBlock Text="Filter" />
        <Button Command="{Binding ClearFiltersCommand}" />
      </StackPanel>
    </DataTemplate>
  </LayoutGroup.HeaderTemplate>

  <!-- Filter controls -->
  <LayoutItem Label="Suchtext">
    <ButtonEdit EditValue="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}" />
  </LayoutItem>

  <LayoutItem Label="Kategorie">
    <ComboBox ItemsSource="{Binding Categories}" SelectedItem="{Binding SelectedCategory}" />
  </LayoutItem>

  <LayoutItem Label="Erstellungsdatum von">
    <DateEdit SelectedDate="{Binding CreatedDateStart}" />
  </LayoutItem>

  <LayoutItem Label="Erstellungsdatum bis">
    <DateEdit SelectedDate="{Binding CreatedDateEnd}" />
  </LayoutItem>

  <LayoutItem Label="Status">
    <ComboBox ItemsSource="{Binding Statuses}" SelectedItem="{Binding SelectedStatus}" />
  </LayoutItem>

  <!-- Add more filter fields... -->
</LayoutGroup>
```

### ViewModel Support:
```csharp
private string _searchText;
private DateTime? _createdDateStart;
private DateTime? _createdDateEnd;
private CategoryDTO _selectedCategory;
private ObservableCollection<CategoryDTO> _categories;

public string SearchText
{
    get => this._searchText;
    set 
    { 
        if (this.SetProperty(ref this._searchText, value, nameof(this.SearchText)))
        {
            this.RefreshList(); // Auto-filter on text change
        }
    }
}

public DelegateCommand ClearFiltersCommand { get; }

public ViewModel()
{
    this.ClearFiltersCommand = new DelegateCommand(() =>
    {
        this.SearchText = string.Empty;
        this.CreatedDateStart = null;
        this.CreatedDateEnd = null;
        this.SelectedCategory = null;
        this.RefreshList();
    });
}
```

---

## WIZARD PATTERN (Multi-Page Workflows)

### Automated Billing Wizard Example:
```xaml
<TabControl SelectedIndex="{Binding CurrentPageIndex}">
  <!-- PAGE 1: Customer Selection -->
  <TabItem Header="Kunden">
    <local:CustomerSelectionWizardPageView />
  </TabItem>

  <!-- PAGE 2: Contract Selection -->
  <TabItem Header="Verträge">
    <local:ContractSelectionWizardPageView />
  </TabItem>

  <!-- PAGE 3: Billing Date -->
  <TabItem Header="Abrechnungszeitraum">
    <local:BillingDateWizardPageView />
  </TabItem>

  <!-- PAGE 4: Send Settings -->
  <TabItem Header="Versendeinstellungen">
    <local:SendSettingsWizardPageView />
  </TabItem>

  <!-- PAGE 5: Overview -->
  <TabItem Header="Übersicht">
    <local:OverviewWizardPageView />
  </TabItem>

  <!-- PAGE 6: Results -->
  <TabItem Header="Ergebnisse">
    <local:BillingResultWizardPageView />
  </TabItem>
</TabControl>

<StackPanel Orientation="Horizontal">
  <Button Command="{Binding PreviousPageCommand}" Content="Zurück" />
  <Button Command="{Binding NextPageCommand}" Content="Weiter" />
  <Button Command="{Binding FinishCommand}" Content="Beenden" />
  <Button Command="{Binding CancelCommand}" Content="Abbrechen" />
</StackPanel>
```

### ViewModel Navigation:
```csharp
private int _currentPageIndex = 0;
public int CurrentPageIndex
{
    get => this._currentPageIndex;
    set => this.SetProperty(ref this._currentPageIndex, value);
}

public DelegateCommand NextPageCommand { get; }
public DelegateCommand PreviousPageCommand { get; }
public AsyncCommand FinishCommand { get; }

public ViewModel()
{
    this.NextPageCommand = new DelegateCommand(
        () => { if (this.CanProceedToNextPage()) this.CurrentPageIndex++; },
        () => this.CurrentPageIndex < 5 && this.CanProceedToNextPage()
    );

    this.PreviousPageCommand = new DelegateCommand(
        () => this.CurrentPageIndex--,
        () => this.CurrentPageIndex > 0
    );

    this.FinishCommand = new AsyncCommand(
        this.ProcessWizard,
        () => this.CurrentPageIndex == 5
    );
}

private bool CanProceedToNextPage()
{
    return this.CurrentPageIndex switch
    {
        0 => this.SelectedCustomers.Any(),
        1 => this.SelectedContracts.Any(),
        2 => this.BillingStartDate.HasValue && this.BillingEndDate.HasValue,
        _ => true
    };
}
```

---

## CONVERTERS & VALUE TRANSFORMATION

### Common Converter Pattern:
```csharp
[ValueConversion(typeof(bool), typeof(Visibility))]
public class BoolToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (bool)value ? Visibility.Visible : Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (Visibility)value == Visibility.Visible;
    }
}

// Usage in XAML:
<TextBlock Visibility="{Binding IsLoading, Converter={StaticResource BoolToVisibilityConverter}}" />
```

### Complex Converter Example (Color String to Brush):
```csharp
public class ColorStringToBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is string colorString)
        {
            return new SolidColorBrush((Color)ColorConverter.ConvertFromString(colorString));
        }
        return Brushes.Black;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

// Status color mapping:
// "Red" → High priority ticket
// "Yellow" → Medium priority
// "Green" → Low priority
// "Orange" → Default value flag
```

---

## VIEWMODEL INHERITANCE HIERARCHY

### Base Classes:
1. **BindableBase** (from Centron.Core.Mvvm)
   - Implements INotifyPropertyChanged
   - Provides SetProperty() method
   - Used for simple data ViewModels (CountryViewModel, FederalStateViewModel)

2. **ViewModelBase** (from DevExpress.Mvvm)
   - Extends BindableBase
   - Adds command support
   - Used for primary module ViewModels (CountryManagementViewModel, AccountManagementViewModel)

3. **ICentronApplication** (interface)
   - Implemented by main App class
   - Provides application-level services

### Mixin Interfaces:
- **IViewModelWithLoading**: Adds IsLoading property, progress tracking
- **IDeferredLoadingCrmPart**: Deferred loading for CRM-related data
- **IViewModelWithCustomProperties**: Custom property support
- **IDisposable**: Resource cleanup (especially for nested ViewModels)

---

## METRICS & STATISTICS

| Metric | Value |
|--------|-------|
| Total XAML Views | 951 |
| Total Modules | 30 |
| Total Submodules | 180+ |
| Reused ViewModels | ~30 (10% of total) |
| Single-Purpose ViewModels | ~270 (90% of total) |
| GridControl instances | ~500 |
| Ribbon implementations | ~150 |
| Tab controls | ~80 |
| Custom converters | ~50+ |
| DevExpress dependency | 24.2.7 |
| Command types used | DelegateCommand, AsyncCommand |
| Collection types | CentronObservableCollection, ObservableCollection |
| Filter dimensions (avg per list) | 5-10 |

---

## BEST PRACTICES OBSERVED

1. **Master-Detail Pattern**: 80% of data entry views
2. **Command-Based Actions**: No code-behind for business logic
3. **Observable Collections**: All mutable data sources
4. **Soft Deletes**: IsDeleted flag, never hard delete
5. **Async Operations**: All I/O operations async (prevents UI freezing)
6. **Filter Collapsibility**: Space-saving filters
7. **Multi-language Support**: All strings via LocalizedStrings
8. **Permission Checks**: Conditional command availability based on user rights
9. **Nested ViewModels**: Complex screens composed of simpler ViewModels
10. **Status Color Coding**: Visual indicators for state/priority
