WPF 对此的回答是什么? [英] What is the WPF answer to this?

查看:35
本文介绍了WPF 对此的回答是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 WPF 开发了两个中等大小的应用程序.WPF 的简洁性及其功能给我留下了深刻的印象.当我向我的一位同事(碰巧开发商业应用程序的人)解释 WPF 的各种好处时,他向我提出了这个问题,这让我感到非常困惑:

I have used WPF to develop two moderately sized applications. I was much impressed by the cleanness of WPF and its features. When I explained to one of my colleagues (Who happens to develop business apps) the various benefits of WPF, he challenged me with this problem which had me totally stumped:

问题:

他在大约 2 分钟内用以下方式编写了一个应用程序:

He coded an application in the following way in about 2 minutes:

  1. 打开一个新的 WinForms 项目.
  2. 定义一个类Loan.
  3. 构建项目.
  4. 使用 Loan 定义对象数据源.
  5. 在数据源资源管理器中,将 Loan 数据源的视图类型更改为详细信息.
  6. 将数据源拖到设计器中的表单上.
  7. 向数据源提供包含一个对象的 Loan[].
  8. 构建并运行应用程序.
  1. Open a new WinForms project.
  2. Define a class Loan.
  3. Build project.
  4. Define an object data source using Loan.
  5. In Data Sources explorer, change view type of the Loan data source to Details.
  6. Drag the data source onto the Form in the designer.
  7. Supply the data source with a Loan[] containing one object.
  8. Build and run application.

代码:

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

设计师:

应用:

现在,每当您更改窗口中AmountRate 的值时,Total 的值都会相应更改.在解释了这是商业应用程序中非常有用的功能之后,您对实体中的一个属性所做的任何更改都会立即更新视图,其中计算的属性会立即刷新,从而使用户体验更好.考虑到典型的业务实体类有很多属性,这样就节省了很多编码.然后他让我在 WPF 中做同样的事情.

Now whenever you change the value of Amount or Rate in the window, the value of Total changes accordingly. After explaining that this is a very useful feature in business apps where any changes you make to one property in an entity immediately updates the view where calculated properties are refreshed instantly making the user experience better. Considering that the typical business entity class has a lot of properties, this saves a lot of coding. Then he asked me to do the same in WPF.

我首先向他解释说我不明白这里发生了什么样的黑魔法.Total 文本框如何自动更新?这是我的第一个问题:

I first explained to him that I do not understand what sort of black magic goes on here. How does the Total textbox update itself automatically? This is my first question:

第一季度.Loan 类没有实现 INotifyPropertyChanged 或类似的东西.那么当 AmountRate 文本框失去焦点时,Total 文本框如何更新?

Q1. The Loan class does not implement INotifyPropertyChanged or something similar. So how does the Total textbox get updated when the Amount or Rate textboxes lose focus?

然后我告诉他,我不知道如何在 WPF 中如此轻松地做同样的事情.但是,我在 WPF 中编写了相同的应用程序,在 UI 中有 3 个 TextBlock 和 3 个 TextBox.我还需要让 Loan 类实现 INotifyPropertyChanged.为 AmountRate 添加了支持字段.每当设置这些属性时,我都会为属性 Total 发出属性更改通知.最后,我得到了一个应用程序,其控件对齐不当,它与 WinForms 应用程序执行相同的操作.然而,这比 WinForms 方法更难做到.

Then I told him that I do not know how to do the same thing so easily in WPF. However, I wrote the same app in WPF with 3 TextBlocks and 3 TextBoxs in the UI. I also needed to make Loan class implement INotifyPropertyChanged. Added backing fields to Amount and Rate. Whenever these properties were being set, I raised a property changed notification for the property Total. In the end, I was left with an app with badly aligned controls which did the same thing as the WinForms app. However, this was way harder to do than the WinForms method.

我回到家,然后有了将 Loan 数据源拖放到 WPF 窗口(在我将视图模式更改为详细信息之后)的好主意.果然,我得到了与 WinForms 应用程序相同类型的 UI,在将数据源设置为与 WinForms 应用程序相同的 Loan[] 后,它似乎是完整的.我运行了应用程序,更改了 AmountRate 字段,希望看到 Total 自动更改自身.然而,我很失望.Total 字段没有改变:

I came home and then had the bright idea of drag-dropping the Loan data source on to the WPF window (After I changed the view mode to detail). Sure enough, I got the same kind of UI as in WinForms app and after setting the data source to the same Loan[] as in WinForms app, it seemed to be complete. I ran the app, changed the Amount and Rate fields hoping to see Total change itself automagically. However, I was disappointed. The Total field did not change:

代码:

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>

第 2 季度.之前我被 WinForms 的黑魔法弄糊涂了,现在我被弄糊涂了,因为同样的黑魔法在 WPF 中不起作用.为什么?

Q2. I was confounded before by the black magic of WinForms, I was confounded now because the same black magic did not work in WPF. Why?

第三季度.如何使 WPF 版本像 WinForms 示例中一样自动更新 Total 字段?

Q3. How do I make the WPF version to update the Total field automatically as in the WinForms example?

第四季度.对于此类业务应用程序开发,哪个平台更好/更快?如果我要代表 WPF 进行更好的论证,我应该注意什么?

Q4. Which platform is better/faster for this sort of business app development? If I am to make a better argument on behalf of WPF, what should I be looking at?

我希望我清楚这个问题.如果需要任何说明,请告诉我.谢谢.

I hope I was clear about the problem. Please let me know if any clarifications are needed. Thanks.

推荐答案

问题 1:如果您查看 Windows 窗体的设计器文件,您将看到为 3 个文本框生成的大约 300 行代码.部分代码类似于:

Q1: If you look at the designer file for the Windows Form you'll see about 300 lines of code generated for your 3 textboxes. Some of this code is similar to:

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

Binding 和 BindingSource 合作更新绑定值,并导致所有绑定控件在每次值更改时更新(使用反射).

The Binding and the BindingSource co-operate to update the bound values and cause all bound controls to be updated every time one of the values changes (using reflection).

问题 2:因为 WPF 设计器不会创建 .Designer.cs 文件和相关的混乱代码.您需要显式实现 INotifyPropertyChange,这可以通过使用 MVVM Light 的 ViewModelBase 来简化,例如

Q2: Because the WPF designer doesn't create a .Designer.cs file and the associated mess of code. You need to explicitly implement INotifyPropertyChange, which can be simplified by using say MVVM Light's ViewModelBase, e.g.

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

Q3:1) 当 Amount 或 Rate 更改引发该属性以及计算属性Total"的属性更改通知时.2) 将 Amount 和 Rate 的绑定修改为 Binding="{Binding Amount, UpdateSourceTrigger=LostFocus}"

Q3: 1) When Amount or Rate changes raise the property change notification for that property but also for the computed property 'Total'. 2) Modify your bindings on Amount and Rate to Binding="{Binding Amount, UpdateSourceTrigger=LostFocus}"

Q4:WPF 没问题(恕我直言).WPF 方式更易于测试、可维护和易于理解.

Q4: WPF no question (IMHO). The WPF way is more testable and maintainable and understandable.

这篇关于WPF 对此的回答是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆