2013-02-13 16 views
6

Ho utilizzato WPF per sviluppare due applicazioni di dimensioni moderate. Sono rimasto molto impressionato dalla pulizia di WPF e dalle sue caratteristiche. Quando ho spiegato a uno dei miei colleghi (che succede a sviluppare applicazioni di business) i vari benefici di WPF, mi ha sfidato con questo problema che mi aveva totalmente perplesso:Qual è la risposta WPF a questo?

Il problema:

ha codificato un applicazione nel modo seguente in circa 2 minuti:

  1. Aprire un nuovo progetto WinForms.
  2. Definire una classe Loan.
  3. Progetto di costruzione.
  4. Definire un'origine dati oggetto utilizzando Loan.
  5. In Explorer origini dati, modificare il tipo di visualizzazione dell'origine dati Loan in Dettagli.
  6. Trascinare l'origine dati sul modulo nella finestra di progettazione.
  7. Fornire l'origine dati con un Loan[] contenente un oggetto.
  8. Costruisci ed esegui l'applicazione.

Il codice:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 

namespace WinForms_DataBinding_Example 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     protected override void OnLoad(EventArgs e) 
     { 
      base.OnLoad(e); 

      loanBindingSource.DataSource = new Loan[] { new Loan() }; 
     } 
    } 

    public class Loan 
    { 
     public decimal Amount { get; set; } 
     public decimal Rate { get; set; } 
     public decimal Total { get { return Amount * Rate; } } 
    } 
} 

Il progettista:

enter image description here

L'applicazione:

enter image description here

Ora ogni volta si modifica il valore di Amount o Rate nella finestra, il valore di Total cambia di conseguenza. Dopo aver spiegato che questa è una funzionalità molto utile nelle app aziendali in cui qualsiasi modifica apportata a una proprietà in un'entità aggiorna immediatamente la vista in cui le proprietà calcolate vengono aggiornate istantaneamente rendendo l'esperienza utente migliore. Considerando che la tipica classe di entità aziendale ha molte proprietà, questo consente di risparmiare un sacco di codice. Poi mi ha chiesto di fare lo stesso in WPF.

Prima gli ho spiegato che non capisco che tipo di magia nera va avanti qui. Come si aggiorna automaticamente la casella di testo ? Questa è la mia prima domanda:

Q1. La classe Loan non implementa INotifyPropertyChanged o qualcosa di simile. Quindi, come viene aggiornata la casella di testo quando le caselle di testo o perdono lo stato attivo?

Poi gli ho detto che non so come fare la stessa cosa così facilmente in WPF. Tuttavia, ho scritto la stessa app in WPF con 3 TextBlock se 3 TextBox s nell'interfaccia utente. Dovevo anche realizzare l'attrezzo Loan della classe INotifyPropertyChanged. Aggiunti i campi di supporto a Amount e Rate. Ogni volta che queste proprietà venivano impostate, ho sollevato una notifica di modifica delle proprietà per la proprietà Total. Alla fine, mi è rimasta una app con controlli mal allineati che ha fatto la stessa cosa dell'app WinForms.Tuttavia, questo era molto più difficile da fare rispetto al metodo WinForms.

Sono tornato a casa e ho avuto la brillante idea di trascinare l'origine dati Loan sulla finestra WPF (dopo aver modificato la modalità di visualizzazione per i dettagli). Abbastanza sicuro, ho avuto lo stesso tipo di interfaccia utente come nell'app WinForms e dopo aver impostato l'origine dati sullo stesso Loan[] come nell'app WinForms, sembrava essere completo. Ho eseguito l'app, modificato i campi Amount e Rate sperando di vedere Total cambiarsi automaticamente. Tuttavia, sono rimasto deluso. Il campo Total non è cambiata:

enter image description here

Il codice:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 
using WinForms_DataBinding_Example; 

namespace WPF_Grid_Example 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
     } 

     private void Window_Loaded_1(object sender, RoutedEventArgs e) 
     { 

      System.Windows.Data.CollectionViewSource loanViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("loanViewSource"))); 
      // Load data by setting the CollectionViewSource.Source property: 
      loanViewSource.Source = new List<Loan>() { new Loan() }; 
     } 
    } 
} 

XAML:

<Window 
     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:WinForms_DataBinding_Example="clr-namespace:WinForms_DataBinding_Example;assembly=WinForms_DataBinding_Example" mc:Ignorable="d" x:Class="WPF_Grid_Example.MainWindow" 
     Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded_1"> 
    <Window.Resources> 
     <CollectionViewSource x:Key="loanViewSource" d:DesignSource="{d:DesignInstance {x:Type WinForms_DataBinding_Example:Loan}, CreateList=True}"/> 
    </Window.Resources> 
    <Grid> 
     <Grid x:Name="grid1" DataContext="{StaticResource loanViewSource}" HorizontalAlignment="Left" Margin="121,123,0,0" VerticalAlignment="Top"> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="Auto"/> 
       <ColumnDefinition Width="Auto"/> 
      </Grid.ColumnDefinitions> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="Auto"/> 
       <RowDefinition Height="Auto"/> 
       <RowDefinition Height="Auto"/> 
      </Grid.RowDefinitions> 
      <Label Content="Amount:" Grid.Column="0" HorizontalAlignment="Left" Margin="3" Grid.Row="0" VerticalAlignment="Center"/> 
      <TextBox x:Name="amountTextBox" Grid.Column="1" HorizontalAlignment="Left" Height="23" Margin="3" Grid.Row="0" Text="{Binding Amount, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" VerticalAlignment="Center" Width="120"/> 
      <Label Content="Rate:" Grid.Column="0" HorizontalAlignment="Left" Margin="3" Grid.Row="1" VerticalAlignment="Center"/> 
      <TextBox x:Name="rateTextBox" Grid.Column="1" HorizontalAlignment="Left" Height="23" Margin="3" Grid.Row="1" Text="{Binding Rate, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" VerticalAlignment="Center" Width="120"/> 
      <Label Content="Total:" Grid.Column="0" HorizontalAlignment="Left" Margin="3" Grid.Row="2" VerticalAlignment="Center"/> 
      <TextBox x:Name="totalTextBox" Grid.Column="1" HorizontalAlignment="Left" Height="23" Margin="3" Grid.Row="2" Text="{Binding Total, Mode=OneWay}" VerticalAlignment="Center" Width="120"/> 
     </Grid> 

    </Grid> 
</Window> 

Q2. Sono stato confuso prima dalla magia nera di WinForms, ero confuso ora perché la stessa magia nera non funzionava in WPF. Perché?

Q3. Come faccio a rendere la versione WPF per aggiornare automaticamente il campo Total come nell'esempio WinForms?

Q4. Quale piattaforma è migliore/più veloce per questo tipo di sviluppo di app aziendali? Se devo fare una discussione migliore per conto di WPF, cosa dovrei guardare?

Spero di essere stato chiaro riguardo al problema. Per favore fatemi sapere se sono necessari chiarimenti. Grazie.

+3

wow .. Sono impressionato, winforms può generare automaticamente uno schermo con 3 caselle di testo ... e allora? qualsiasi altra cosa è impossibile in winforms, mentre WPF ti dà la possibilità di personalizzare TUTTO e di associare QUALSIASI COSA a QUALSIASI COSA, non solo, ad esempio la proprietà Text, come in winforms. Le applicazioni line-of-business del mondo reale non sono semplici caselle di testo, richiedono una logica molto complessa, e Winform richiede un codice infernale per fare applicazioni reali, contro le proprietà semplici e XAML. –

+0

@HighCore: sono sicuro che hai ragione. Ma il tuo commento non risponde a nessuna delle mie domande. :( – nakiya

+0

In generale, mi sembra che si stiano confrontando due framework basati su un caso d'uso specifico, non credo che porti a risultati equi – Ameen

risposta

5

Q1: Se si guarda il file di progettazione per Windows Form, verranno visualizzate circa 300 righe di codice generate per le 3 caselle di testo. Parte di questo codice è simile a:

this.amountTextBox.DataBindings.Add(
    new System.Windows.Forms.Binding("Text", 
     this.loanBindingSource, "Amount", true)); 

The Binding e BindingSource cooperano per aggiornare i valori legati e causare tutti controlli associati a essere aggiornati ogni volta che uno dei valori modifiche (utilizzando la riflessione).

Q2: Perché il progettista WPF non crea un file .Designer.cs e il pasticcio di codice associato. È necessario implementare in modo esplicito INotifyPropertyChange, che può essere semplificato utilizzando ad esempio ViewModelBase di MVVM Light, ad es.

public class Loan : ViewModelBase 
{ 
    public decimal Amount 
    { 
     get 
     { 
      return this.amount; 
     } 
     set 
     { 
      if (Set(() => Amount, ref this.amount, value)) 
      { 
       RaisePropertyChanged(() => Total); 
      } 
     } 
    } 

Q3: 1) quando somma o il tasso di cambiamenti sollevano la notifica di modifica di proprietà per la proprietà, ma anche per la proprietà calcolata 'totale'. 2) Modificare i collegamenti su Quantità e tariffa su

Q4: WPF nessuna domanda (IMHO). La modalità WPF è più testabile, manutenibile e comprensibile.

1

Risposta a Q4:

Indipendentemente WinForms che hanno la capacità di generare 3 caselle di testo stupide per una classe, WPF è un quadro molto migliore, scalabile e potente. Ha molto maggiori prestazioni a causa di accelerazione hardware e quant'altro, e richiede meno o nessun codice per fare alcuni compiti che prendono un sacco di codice in WinForms, come ad esempio this, o questo:

<CheckBox x:Name="chk"/> 
<TextBox IsEnabled="{Binding IsChecked,ElementName=chk}"/> 

Inoltre, tipica Portata della -Le applicazioni aziendali devono gestire migliaia o centinaia di migliaia di record e UI Virtualization makes a huge difference.

La linea di fondo è che winforms, a prescindere dal fatto di avere alcune chicche per gli stilisti (che sono più una caratteristica di Visual Studio rispetto a Winforms stesso), non è neanche lontanamente pratico e adeguato quando si tratta di Line of Business.

Problemi correlati