如何在这个模型中应用MVVM模式?

时间:2011-09-05 18:47:30

标签: c# wpf design-patterns

问题始于这篇文章:Using binding to a List<UserControl> how can I do for not showing the controls

我正在设计这样的东西:

List<Container>
(Below container properties)
    - Objective: string
    - Problems: List<ProblemUserControl>

ProblemUserControls是一个UserControl,其中包含一个名为Problem的额外属性。但上面的帖子一个人建议我使用MVVM Pattern。我正在调查,但我仍然感到困惑,或者我需要一些帮助来理解WPF中的模式。

2 个答案:

答案 0 :(得分:1)

该模式是关于在软件的逻辑层之间保持适当的分离和依赖关系。您在示例中将显示逻辑与业务逻辑混淆,因为您将模型代码(目标容器)与显示代码(用户控件列表)混合在一起。

相反,请保持目标并维持List<Problem>而不是List<ProblemUserControl>。然后使用WPF和绑定将ProblemUserControlProblem相关联。您的用户控件了解Problem是什么,因此您可以绑定Problem上的属性。通过这种方式,您可以对图层进行隔离,从而更容易推断出您的软件。

答案 1 :(得分:1)

以下是使用MVVM进行说明的示例。请注意,不需要有一个用户控件列表,从MVVM角度来看,这实际上被认为是不正确的。

这是基于Visual Studio中的默认WPF应用程序模板。

以下是所涉及的课程。

public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler changed = PropertyChanged;
        if (changed != null)
        {
            changed(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

public class Container : ViewModelBase
{
    private string m_Objective;
    private ProblemCollection m_Problems;

    public Container()
    {
        m_Problems = new ProblemCollection();
    }

    public string Objective
    {
        get { return m_Objective; }
        set
        {
            m_Objective = value;
            OnPropertyChanged("Objective");
        }
    }

    public ProblemCollection Problems
    {
        get { return m_Problems; }
        set
        {
            m_Problems = value;
            OnPropertyChanged("Problems");
        }
    }
}

public class Problem : ViewModelBase
{
    private string m_Name;

    public string Name
    {
        get { return m_Name; }
        set
        {
            m_Name = value;
            OnPropertyChanged("Name");
        }
    }
}

public class ProblemCollection : ObservableCollection<Problem>
{
}

主窗口。请注意,我已注释掉您的矩形以显示绑定

<Window x:Class="StackOverflowDemo.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525">
  <Grid>
    <TextBlock TextWrapping="Wrap" Text="{Binding Objective}" Grid.Column="0" VerticalAlignment="Center"
        FontWeight="Bold" />
    <ItemsControl ItemsSource="{Binding Problems}">
      <ItemsControl.ItemTemplate>
        <DataTemplate>
          <!--<Rectangle Stroke="Black" Height="20" Width="20" Margin="1,0" />-->
          <TextBlock Text="{Binding Path=Name}" />
        </DataTemplate>
      </ItemsControl.ItemTemplate>
    </ItemsControl>
  </Grid>
</Window>

MainWindow.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        // Create dummy test data.
        // Normally this will be passed to the window or set externally
        var container = new Container();
        container.Problems.Add(new Problem {Name = "Foo"});
        container.Problems.Add(new Problem {Name = "Bar"});
        container.Problems.Add(new Problem {Name = "hello"});
        container.Problems.Add(new Problem {Name = "world"});

        DataContext = container;
    }
}