2

The problem begins at this post: Using binding to a List<UserControl> how can I do for not showing the controls

I was designing something like this:

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

ProblemUserControls is a UserControl where contais an extra property called Problem. But the above post a person suggest me use MVVM Pattern. I'm investigating but, I'm still confused or I need a little of help to understand the pattern in WPF.

Community
  • 1
  • 1
Darf
  • 2,495
  • 5
  • 26
  • 37
  • Doesn't answer the question directly but might be of some use - http://stackoverflow.com/questions/1939403/mvvm-viewmodel-vs-mvc-viewmodel/1939606#1939606 – Adam Ralph Sep 05 '11 at 18:52

2 Answers2

1

The pattern is about maintaining proper separation and dependencies between logical layers of your software. You're confusing Display logic with business logic in your example because you're mixing your model code (the Container of Objectives) with your display code (a list of Usercontrols.)

Instead, keep your objectives and maintain a List<Problem> instead of a List<ProblemUserControl>. Then use WPF and binding to associate your ProblemUserControl with a Problem. Your user control understands what a Problem is, so you can bind against properties on the Problem. This way you segregate your layers and make it much easier to reason about your software in general.

Greg D
  • 43,259
  • 14
  • 84
  • 117
  • Greg, I guess I understand what you're trying to tell me. But I cannot figure how can I start building the application – Darf Sep 05 '11 at 19:56
  • One step at a time. No magic bullet here: just start doing it, making mistakes, and learning from them. – Greg D Sep 06 '11 at 11:25
1

Here is a example to illustrate using MVVM. Note that there is no need to have a list of usercontrols and indeed this would be considered incorrect from an MVVM viewpoint.

This is based on the default WPF application template in Visual studio.

Here are the classes involved.

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

And the main window. Note that I've commented out your rectangle to show the bindings

<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;
    }
}
bic
  • 2,201
  • 26
  • 27