What is WPF answer to this?

I used WPF to develop two medium-sized applications. I was very impressed with the cleanliness of WPF and its features. When I explained to one of my colleagues (Who is developing business applications) the various advantages of WPF, he challenged me with this problem, which completely surpassed me:

Problem:

He encoded the application as follows after about 2 minutes:

  • Open a new WinForms project.
  • Define the Loan class.
  • Build a project.
  • Define the data source of the object using Loan .
  • In the "Data Source", change the presentation type of the Loan data source to "Details."
  • Drag the data source into the form in the designer.
  • Put the data source with Loan[] containing one object.
  • Build and run the application.

The code:

 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; } } } } 

Designer:

enter image description here

Application:

enter image description here

Now, when you change the Amount or Rate value in the window, the Total value changes. Explaining that this is a very useful feature in business applications, where any changes you make to a single property in essence immediately update the view in which the calculated properties are updated, which makes the user’s work better. Given that a typical business entity class has many properties, this saves a lot of coding. He then asked me to do the same in WPF.

At first I explained to him that I did not understand what black magic was. How is the Total text box automatically updated? This is my first question:

Q1. The Loan class does not implement INotifyPropertyChanged or something like that. So, how is the Total text box updated when the Amount or Rate text fields lose focus?

Then I told him that I did not know how to do the same thing so easily in WPF. However, I wrote the same application in WPF with 3 TextBlock and 3 TextBox in the user interface. I also needed to implement the Loan class INotifyPropertyChanged . Added support fields Amount and Rate . Whenever these properties are set, I raised the property change notification for the Total property. In the end, I was left with an application with poorly aligned controls that did the same thing as the WinForms application. However, it was more complicated than the WinForms method.

I came home and then proposed the bright idea of ​​dragging a Loan data source into a WPF window (after I changed the view mode to details). Of course, I got the same interface as in the WinForms application, and after installing the data source in the same Loan[] as in the WinForms application, it seemed to be complete. I launched the application, changed the Amount and Rate fields, hoping that Total will automatically change itself. However, I was disappointed. The Total field has not changed:

enter image description here

The code:

 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. I was confused before with WinForms black magic, now I was confused because the same black magic did not work in WPF. Why?

Q3. How to force the WPF version to update the Total field automatically, as in the WinForms example?

Q4. Which platform is better / faster for this kind of business application? If I should make a better argument on behalf of WPF, what should I look at?

Hope I understood the problem. Please let me know if any clarification is needed. Thanks.

+6
source share
2 answers

Q1: If you look at the constructor file for Windows Form, you will see about 300 lines of code created for your three text fields. Some of this code is similar to:

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

Binding and BindingSource work together to update related values ​​and cause all related controls to be updated every time one of the values ​​changes (using reflection).

Q2: Because the WPF designer does not create the .Designer.cs file and the associated code clutter. You need to explicitly implement INotifyPropertyChange, which can be simplified using, for example, MVVM Light ViewModelBase, for example.

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

Q3: 1) When changes in the amount or rate increase the notification of a change in a property for this property, but also for the calculated Total property. 2) Change the bindings to the amount and speed to Binding="{Binding Amount, UpdateSourceTrigger=LostFocus}"

Q4: WPF no questions asked (IMHO). The WPF method is more tested and convenient and clear.

+5
source

Answer to Q4:

Regardless of winforms having the ability to generate 3 stupid text fields for a class, WPF is a much better, scalable and powerful infrastructure. It has much greater performance due to hardware acceleration and something else and requires less or no code to perform some tasks that take tons of code in winforms like this , or this

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

In addition, typical Line of Business applications must deal with thousands or hundreds of thousands of records, and UI virtualization is of the utmost importance .

The bottom line is that winforms, regardless of the presence of any design positive qualities (which are rather a hallmark of Visual Studio than winforms), nowhere comes close to practical and adequate when it comes to Line of Business.

+1
source

All Articles