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

时间:2017-05-09 10:16:28

标签: c# wpf mvvm data-binding mvp

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

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

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

我的问题是我如何展示它们

在MVVM中,我将列表绑定到ListBox原因,这就是MVVM“做”的原因。 EG

<Window.Resources>
  <DataTemplate DataType="{x:type model:Mymodel}">
    //Some DataTemplate Definition
  </DataTemplate>
</Window.Resources>

然后绑定到我的Listbox

<ListBox ItemSources={Binding someProperty} />

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

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

你不应该绑定MVP中的任何内容,因为它不是应该如何工作,或者我错了吗?

因此,如果我不应该绑定数据,如何在ListBox中显示我的模型对象列表,这样就不会说

Model Object
Model Object
Model Object
Model Object

我知道您应该将MVVM用于WPF,但为了证明为什么它更好我需要展示MVP如何在WPF中工作。

2 个答案:

答案 0 :(得分:3)

当你使用WPF时,就像你所说的那样,通过数据绑定来使用MVVM。 MVP通常与Windows形式一起使用,其中没有数据绑定可用。如果您希望您的应用程序具有相同的功能并使用相同的技术(WPF),则无法避免使用绑定,或者至少更难以执行。只要您通过演示者与模型交谈,您仍然在使用MVP。您可以自行决定是否要使用

  • 被动视图 - 演示者处理视图和模型之间的所有对话
  • SuperVising Presenter - View了解模型,演示者处理视图和模型之间需要处理的“难度代码”。

如果你正在使用绑定我会说(不确定)你使用的是 SuperVising Presenter ,这不是“推荐”,但是不建议在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>

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

答案 1 :(得分:1)

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

从您已展示的示例中我将开始并将 View 绑定到 Presenter ,这应该是 View 和模型,你可以在这里看到:
MVP scheme from wikipedia
(来自wikipedia article的图片)

查看应该向演示者发送事件/更改,演示者应该是&#34;大脑/逻辑&#34; View 决定是否应该更新 Model

假设您拥有 View ,就像这样:

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

您可以像这样创建一个 Presenter

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

模型可能如下所示:

public class ListItem
{
    ListItemPresenter m_Presenter;

    public ListItemPresenter GetPresenter()
    {
        return m_Presenter;
    }

    string m_ElementContent;

    public string ElementContent
    {
        get { return m_ElementContent; }
        set { m_ElementContent = value; }
    }

    public ListItem(ListItemPresenter presenter)
    {
        m_Presenter = presenter;
    }
}

使用 Presenter 的另一种方式可能如下:

假设您有类似的查看,只需创建一个演示者

public class Presenter
{
    ObservableCollection<ListItem> m_ListItems = new ObservableCollection<ListItem>(); 

    public ObservableCollection<List> ListItems
    {
        get { return m_ListItems; }
    }

    public Presenter(MeView view)
    { 
        Binding binding = new Binding("ListItems");
        binding.Source = ListItems;
        view.MeListView.SetBinding(ListView.ItemsSourceProperty, binding);
        // other view events, bindings etc.
    }
}

这不是间接地在 View Model 之间进行通信的最佳方式,但应该给你一些小提示。如果您希望拆分控件,每个控件都拥有自己的 Presenter ,或者每个窗口需要一个控件,这将取决于您。