Użyłem WPF do opracowania dwóch umiarkowanie dużych aplikacji. Byłem pod wrażeniem czystości WPF i jej funkcji. Kiedy wyjaśnił jeden z moich współpracowników (który akurat do rozwijania aplikacji biznesowych) różne korzyści WPF, wyzwał mnie z tym problemem, który miał mi zupełnie zakłopotany:Jaka jest odpowiedź WPF na to?
Problem:
on zakodowany aplikacja w następujący sposób za około 2 minuty:
- Otwórz nowy projekt WinForms.
- Zdefiniuj klasę
Loan
. - Projekt budowy.
- Definiowanie źródła danych obiektu za pomocą
Loan
. - W Eksploratorze źródeł danych zmień typ widoku źródła danych
Loan
na Szczegóły. - Przeciągnij źródło danych na formularz w projektancie.
- Dostarcz źródło danych do
Loan[]
zawierającego jeden obiekt. - Utwórz i uruchom aplikację.
Kod:
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; } }
}
}
Projektant:
Aplikacja:
Teraz ilekroć zmieniasz wartość Amount
lub Rate
w oknie, wartość Total
zmienia się odpowiednio. Po wyjaśnieniu, że jest to bardzo przydatna funkcja w aplikacjach biznesowych, w której wszelkie zmiany wprowadzane w jednej usłudze w jednostce natychmiast aktualizują widok, w którym obliczone właściwości są odświeżane natychmiast, poprawiając komfort użytkownika. Biorąc pod uwagę, że typowa klasa jednostek biznesowych ma wiele właściwości, oszczędza to wiele kodowania. Potem poprosił mnie, żebym zrobił to samo w WPF.
Najpierw wyjaśniłem mu, że nie rozumiem, jaka to czarna magia. W jaki sposób pole tekstowe Total
aktualizuje się automatycznie? To jest moje pierwsze pytanie:
Q1. Klasa Loan
nie implementuje INotifyPropertyChanged
lub czegoś podobnego. Więc w jaki sposób pole tekstowe Total
jest aktualizowane, gdy pola tekstowe tracą ostrość?
Potem powiedziałem mu, że nie wiem jak zrobić to samo tak łatwo w WPF. Jednak napisałem tę samą aplikację w WPF z 3 TextBlock
s i 3 TextBox
s w interfejsie użytkownika. Musiałem również wykonać klasę Loan
implementacji urządzenia INotifyPropertyChanged
. Dodano pola pomocnicze do Amount
i Rate
. Kiedykolwiek te właściwości były ustawiane, podniosłem powiadomienie o zmianie właściwości dla właściwości Total
. W końcu zostałem z aplikacją ze źle wyrównanymi kontrolkami, które zrobiły to samo, co aplikacja WinForm.Jednak było to o wiele trudniejsze niż metoda WinForms.
Przyszedłem do domu, a następnie wpadłem na pomysł, by przeciągnąć źródło danych z Loan
do okna WPF (Po zmianie trybu widoku na szczegóły). Oczywiście, mam ten sam rodzaj interfejsu jak w aplikacji WinForms i po ustawieniu źródła danych na ten sam Loan[]
jak w aplikacji WinForms, wydawało się, że jest kompletny. Uruchomiłem aplikację, zmieniłem pola, mając nadzieję, że zmienią się automagicznie na Total
. Jednak byłem rozczarowany. Pole Total
nie uległa zmianie:
kodu:
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. Byłem oszołomiony wcześniej przez czarną magię WinForms, byłem teraz zdezorientowany, ponieważ ta sama czarna magia nie działała w WPF. Czemu?
Q3. Jak sprawić, aby wersja WPF aktualizowała automatycznie pole Total
, tak jak w przykładzie WinForm?
Q4. Która platforma jest lepsza/szybsza w przypadku tego rodzaju tworzenia aplikacji biznesowych? Jeśli mam przedstawić lepszy argument w imieniu WPF, na co powinienem zwrócić uwagę?
Mam nadzieję, że nie miałem wątpliwości co do tego problemu. Proszę dać mi znać, czy potrzebne są jakieś wyjaśnienia. Dzięki.
wow .. Jestem pod wrażeniem, WinForm może automatycznie wygenerować ekran z 3 polami tekstowymi ... i co z tego? wszystko inne jest niemożliwe w WinForm, podczas gdy WPF daje możliwość dostosowania WSZYSTKIEGO i związania WSZYSTKIEGO z NIMI, nie tylko, powiedz właściwość Tekst, jak w winformach. PRAWDZIWY świat Aplikacje Line-of-Business to nie proste pola tekstowe, wymagają one dużo bardziej skomplikowanej logiki, a winFormy wymagają ogromnego kodu do wykonywania rzeczywistych aplikacji, w przeciwieństwie do prostych właściwości i XAML. –
@HighCore: Jestem pewien, że masz rację. Ale twój komentarz nie odpowiada na żadne z moich pytań. :( – nakiya
Ogólnie rzecz biorąc, wydaje mi się, że porównujesz dwa frameworki oparte na konkretnym przypadku użycia.Nie myślę, że prowadzi to do uczciwych wyników. – Ameen