C# 我应该通过绑定使用MVP和WPF显示数据吗?

C# 我应该通过绑定使用MVP和WPF显示数据吗?,c#,wpf,mvvm,data-binding,mvp,C#,Wpf,Mvvm,Data Binding,Mvp,我正在写一篇关于代码设计的论文,我正在比较MV-C、p和VM,看看哪一个最适合WPF。在我的研究中,我意识到MVVM是其他标准中数据绑定的明显选择原因 即使我知道这一点,我也必须在某种意义上“证明”这一点,因此我在MVP和MVVM中创建了一个应用程序,它做的事情完全相同,但处理代码的方式不同。通过本文,我将解释这些代码模式的优缺点,但在使用MVP应用程序创建时,我遇到了一个问题 我有一个带有“业务逻辑”的模型,我的演示者创建了这些模型对象的列表,我的视图可以显示这些对象 我的问题是如何显示它们

我正在写一篇关于代码设计的论文,我正在比较MV-C、p和VM,看看哪一个最适合WPF。在我的研究中,我意识到MVVM是其他标准中数据绑定的明显选择原因

即使我知道这一点,我也必须在某种意义上“证明”这一点,因此我在MVP和MVVM中创建了一个应用程序,它做的事情完全相同,但处理代码的方式不同。通过本文,我将解释这些代码模式的优缺点,但在使用MVP应用程序创建时,我遇到了一个问题

我有一个带有“业务逻辑”的模型,我的演示者创建了这些模型对象的列表,我的视图可以显示这些对象

我的问题是如何显示它们

在MVVM中,我将我的列表绑定到一个
ListBox
,因为这就是MVVM的“制造”方式。 乙二醇

它没有完全编码,但是你得到了这个手势

但是,如果我理解正确的话,与MVP的绑定不应该是这样的

你不应该在MVP中绑定任何东西,因为这不是它应该如何工作的,还是我错了

所以,如果我不应该绑定数据,我怎么能在
列表框中显示我的模型对象列表呢

Model Object
Model Object
Model Object
Model Object

我理解您应该在WPF中使用MVVM,但为了证明为什么它更好,我需要展示MVP如何在WPF中工作。我无法在评论中添加我想要的代码,因此我将发布一个答案。如果有什么不清楚的地方,给我一个反馈,我会给你更多的细节

从您展示的示例中,我将继续进行从视图到演示者的绑定,这应该是视图和模型之间的桥梁,您可以在这里看到:

(图片来源)

视图应该向演示者发送事件/更改,演示者应该是视图的“大脑/逻辑”,决定是否应该更新模型


假设您有这样的视图:

<UserControl x:Class="EntryNamespace.MeView"
    ... >

    <!-- ListItems should return collection of Presenters -->
    <ListView ItemsSource="{Binding ListItems, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <!-- Elementcontent should be a property inside Presenter that returns value from Model -->
                <Button Content="{Binding ElementContent}"/>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

</UserControl>
class Presenter : INotifyPropertyChanged
{
    public ObservableCollection<ListItemPresenter> ListItems
    {
        get { return GetItems(); }
        set { SetItems(value); }
    }

    ObservableCollection<ListItemPresenter> GetItems()
    {
        // private logic to retrieve `ListItemPresenter` collection from model

        var collection = new ObservableCollection<ListItemPresenter>();
        foreach(ListItem listItem in Model.Items)
            collection.Add(listItem.GetPresenter());

        return collection;
    }

    void SetItems(ObservableCollection<ListItemPresenter> objects)
    {
        // private logic to transfer `ListItemPresenter` collection to model
        // remember to call NotifyPropertyChanged("ListItems");

        Model.Items.Clear();
        foreach(ListItemPresenter presenter in objects)
            Model.Items.Add(presenter.GetModel());

        NotifyPropertyChanged("ListItems");
    }
}

使用Presenter的另一种方法如下所示:

假设您有类似的视图,只需创建一个演示者:

公共类演示者
{
ObservableCollection m_ListItems=新的ObservableCollection();
公共可观察收集列表项
{
获取{return m_ListItems;}
}
公共演示者(MeView)
{ 
绑定=新绑定(“列表项”);
binding.Source=列表项;
view.MeListView.SetBinding(ListView.ItemsSourceProperty,绑定);
//其他视图事件、绑定等。
}
}


这不是视图和模型之间间接交流的最佳方式,但应该给您一些提示。如果您希望拆分控件,使每个控件都有自己的演示者,或者希望每个窗口都有一个演示者,则由您决定。

我无法在注释中添加尽可能多的代码,因此我将发布一个答案。如果有什么不清楚的话,给我一个反馈,我会给你更多的细节

从您展示的示例中,我将继续进行从视图到演示者的绑定,这应该是视图和模型之间的桥梁,您可以在这里看到:

(图片来源)

视图应该向演示者发送事件/更改,演示者应该是视图的“大脑/逻辑”,决定是否应该更新模型


假设您有这样的视图:

<UserControl x:Class="EntryNamespace.MeView"
    ... >

    <!-- ListItems should return collection of Presenters -->
    <ListView ItemsSource="{Binding ListItems, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <!-- Elementcontent should be a property inside Presenter that returns value from Model -->
                <Button Content="{Binding ElementContent}"/>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

</UserControl>
class Presenter : INotifyPropertyChanged
{
    public ObservableCollection<ListItemPresenter> ListItems
    {
        get { return GetItems(); }
        set { SetItems(value); }
    }

    ObservableCollection<ListItemPresenter> GetItems()
    {
        // private logic to retrieve `ListItemPresenter` collection from model

        var collection = new ObservableCollection<ListItemPresenter>();
        foreach(ListItem listItem in Model.Items)
            collection.Add(listItem.GetPresenter());

        return collection;
    }

    void SetItems(ObservableCollection<ListItemPresenter> objects)
    {
        // private logic to transfer `ListItemPresenter` collection to model
        // remember to call NotifyPropertyChanged("ListItems");

        Model.Items.Clear();
        foreach(ListItemPresenter presenter in objects)
            Model.Items.Add(presenter.GetModel());

        NotifyPropertyChanged("ListItems");
    }
}

使用Presenter的另一种方法如下所示:

假设您有类似的视图,只需创建一个演示者:

公共类演示者
{
ObservableCollection m_ListItems=新的ObservableCollection();
公共可观察收集列表项
{
获取{return m_ListItems;}
}
公共演示者(MeView)
{ 
绑定=新绑定(“列表项”);
binding.Source=列表项;
view.MeListView.SetBinding(ListView.ItemsSourceProperty,绑定);
//其他视图事件、绑定等。
}
}


这不是视图和模型之间间接交流的最佳方式,但应该给您一些提示。如果您希望拆分控件,使每个控件都有自己的Presenter,或者希望每个窗口都有一个Presenter,这将取决于您。

当您使用WPF时,正如您所说,通过数据绑定与MVVM一起工作。MVP通常用于没有数据绑定的Windows窗体。如果您希望应用程序具有相同的功能并使用相同的技术(WPF),则无法避免使用绑定,或者至少更难做到这一点。只要你通过演示者与你的模特交谈,你仍然在使用MVP。如果你想使用,你可以自己决定

  • 被动视图-演示者处理视图和模型之间的所有对话框
  • 监督演示者-视图了解模型,演示者处理在视图和模型之间需要处理的“困难代码”
如果您使用的是绑定,我会说(不确定)您使用的是监督演示者,这是不“推荐”的,但在WPF中使用MVP也是不推荐的,所以

编辑示例

例如,如果要显示列表,则需要有一个界面,该界面的属性为包含要显示的对象的列表

public interface myinterface
{
  ObservableCollection<YourModel> ListName {get; set;}
}
在你看来

<ListBox ItemSource ={Binding ListName}>
  <ListBox.ItemTemplate>Set how you want to display the list</ListBox.ItemTemplate>

设置要显示列表的方式

这是一个不清楚的例子,但希望能让您了解MVP是如何与WPF一起工作的(以一种小的方式)

当您使用WPF时,正如您所说的,通过数据绑定与MVVM一起工作。MVP通常用于没有数据绑定的Windows窗体。如果您希望应用程序具有相同的功能并使用相同的技术(WPF),则无法避免使用绑定,或者至少更难做到这一点。只要你通过演示者与你的模特交谈,你仍然在使用MVP。如果你想使用,你可以自己决定

  • public interface myinterface { ObservableCollection<YourModel> ListName {get; set;} }
private myinterface _my;
public Presenter(myinterface my)
{ this._my = my;}

_my.ListName = // Add whatever Data you want into this list.
<ListBox ItemSource ={Binding ListName}>
  <ListBox.ItemTemplate>Set how you want to display the list</ListBox.ItemTemplate>