0

I'm trying to understand this pattern and all the logic that's behind it.

I don't think it's that hard, but still I'm failing in some easy tasks.

Let's make it clear with a non-working example that I wrote:

Model:

public class Model
{
    public string Name { get; set; }
    public string Description { get; set; }
    public Categories Category { get; set; }
    public Grid PresenterContent { get; set; }
}

ViewModel:

public class ViewModel : ViewModelBase
{
    private Model _model;
    public Model Model 
    {
        get
        {
            return _model;
        }
        set
        {
            if (_model != value)
            {
                _model = value;
                RaisePropertyChanged(() => Model);
            }
        }
    }

    public Grid PresenterContent
    {
        get
        {
            return Model.PresenterContent;
        }
        private set { }
    }

    public ViewModel()
    {
        Model = new Model();            
    }
}

View:

<UserControl.DataContext>
    <Binding Source="ViewModel"/>
</UserControl.DataContext>

<Grid x:Name="LayoutRoot" Background="{StaticResource PhoneChromeBrush}">
    <ContentPresenter Content="{Binding PresenterContent}"/>        
</Grid>

Now, I expect this to work when I run it, as I'm setting the DataContext to ViewModel which has a PresenterContent property.

(This property is both in the Model and the ViewModel because I don't know to work with child's property, in this case Model.PresenterContent.)

What actually happens is that an exception is thrown:

System.Windows.Data Error: BindingExpression path error: 'PresenterContent' property not found on 'ViewModel' 'System.String' (HashCode=-903444198). BindingExpression: Path='PresenterContent' DataItem='ViewModel' (HashCode=-903444198); target element is 'System.Windows.Controls.ContentPresenter' (Name=''); target property is 'Content' (type 'System.Object')..

and this says that there's no PresenterContent in the ViewModel, which is clearly wrong. The exception is the same if I try to bind to Model property.

What am I doing wrong?

4

2 回答 2

2

The problem is that you are Setting the Source of the binding of UserControl.DataContext to the string ViewModel instead of an instance of ViewModel (that's why your error say "on 'ViewModel' 'System.String'")

.
To make it work you could for example use:

<UserControl.DataContext>
    <vm:ViewModel/>
</UserControl.DataContext>

Or you could define you ViewModel in App.xaml or in your View resource <vm:ViewModel x:Key="myViewModel"/> and in you view use:

<UserControl.DataContext>
    <Binding Source="{StaticResource myViewModel}"/>
</UserControl.DataContext>
于 2013-09-16T18:50:23.970 回答
1

You shouldn't be putting a UserControl (like Grid) in your view model; that's the beauty of the View. Based on your example, you probably want a control like the DataGrid, which displays things in an Excel-like table. Consider the following:

public class Model
{
    public string Name { get; set; }
    public string Description { get; set; }
    public Categories Category { get; set; }
    public Grid PresenterContent { get; set; }
}

public class ViewModel : ViewModelBase
{
    private ObservableCollection<Model> _model;
    public ObservableCollection<Model> Model
    {
        get
        {
            return _model;
        }
        set
        {
            if (_model != value)
            {
                _model = value;
                RaisePropertyChanged(() => Model);
            }
        }
    }

    public ViewModel()
    {
        Model = new ObservableCollection<Model>();
    }
}

This is what is in the code-behind (may not be exactly like this):

public partial class UserControl1 : public UserControl
{
    UserControl1( )
    {
        this.DataContext = new ViewModel( );
    }
}

And the Xaml would look like this:

<DataGrid ItemsSource="{Binding Model}" />

The idea is that your ViewModel prepares the data for presentation, and the entire presentation is defined in the Xaml (View). Using the "{Binding xxx}" you may access properties on the object that is the 'DataContext' of the current control. So the Xaml defines the children of the UserControl, and every UserControl has a DataContext to which objects on the UI (Xaml) can be bound. So you can bind your DataGrid's ItemsSource (the source of the items that populate the grid) to the DataContext's Model property by saying ItemsSource="{Binding Model}"

于 2013-09-16T18:53:04.447 回答