How to instantiate a ViewModel in a data template

I am a new developer in WPF, universal applications, etc.

I created a view to display questions.

I have a QuestionViewModel that provides a collection of Questions. In XAML, I use ItemsControl to display questions.

Now in the DataTemplate, I would like to use a user control to display a question, create an instance of my QuestionViewModel, associate the current question with it and set the view model in the context of the user control. My problem is that {Binding} does not give me a question, I have a Binding object: /

Should I do this? How to get current question in ViewModel?


the code

public class Question : AEntity, IQuestion
{
    public Question(String title, String answer) : base()
    {
        this.Title = title;
        this.Answer = answer;
    }


    public string Title { get; set; }
    public string Answer { get; set; }
}

public class QuestionsViewModel : BaseViewModel
{
    private String description;

    public QuestionsViewModel()
    {
        ObservableCollection<Question> questions = new ObservableCollection<Question>();
        questions.CollectionChanged += Questions_CollectionChanged;
        Questions = questions;
        AddQuestionCommand = new AddQuestionCommand(Questions);
        AddQuestionCommand.Execute(null);//add a question for test
    }

    private void Questions_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        Description = String.Format("{0} question(s)", Questions.Count);
    }

    public ICollection<Question> Questions { get; private set; }

    public ICommand AddQuestionCommand { get; private set; }

    public String Description {
        get { return description; }
        set
        {
            description = value;
            onPropertyChanged("Description");
        }
    }
}

public class QuestionViewModel : BaseViewModel
{
    private Question question;

    public QuestionViewModel()
    {
    }

    public Question Question { get; set; }

}

View questions

<UserControl  x:Class="Question_Answer.View.Control.QuestionsControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:model="using:Question_Answer.Model"
xmlns:uc="using:Question_Answer.View.Control"
xmlns:vm="using:Question_Answer.ViewModel.Control"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">

<UserControl.DataContext>
    <vm:QuestionsViewModel Description="view description">  </vm:QuestionsViewModel>        
</UserControl.DataContext>

<ItemsControl Name="Questions" Grid.Row="1" Grid.ColumnSpan="2" ItemsSource="{Binding Questions}">
    <ItemsControl.ItemTemplate>
            <DataTemplate x:DataType="model:Question">
                <uc:QuestionItemControl>
                    <uc:QuestionItemControl.DataContext>
                        <vm:QuestionViewModel Question="{Binding}" />
                    </uc:QuestionItemControl.DataContext>
                </uc:QuestionItemControl>
            </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
</UserControl>

User User Control

<UserControl
x:Class="Question_Answer.View.Control.QuestionItemControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Question_Answer.View.Control"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"></ColumnDefinition>
        <ColumnDefinition Width="*"></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <TextBlock Grid.Column="0" Text="{Binding Question.Title}" />
    <TextBlock Grid.Column="1" Text="{Binding Question.Answer}" />
</Grid>

+4
3

- .

.

public class QuestionsViewModel:ViewModelBase
{
    private String description;
    public ObservableCollection<Question> questions { get; set; }
    public QuestionsViewModel()
    {
        questions = new ObservableCollection<Question>();
        questions.CollectionChanged += Questions_CollectionChanged;
        questions.Add(new Question("t1","a1"));


    }

    private void Questions_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        Description = String.Format("{0} question(s)", e.NewItems.Count);
    }



    public String Description
    {
        get { return description; }
        set
        {
            description = value;
            RaisePropertyChanged("Description");
        }
    }
}

public class QuestionViewModel:ViewModelBase
{
    private Question question;

    public QuestionViewModel()
    {
    }
    public Question Question
    {
        get { return question; }
        set
        {
            question = value;
            RaisePropertyChanged("Question");
        }
    }
}
<UserControl
x:Class="AppMvvm2.QuestionItemControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:AppMvvm2"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"></ColumnDefinition>
        <ColumnDefinition Width="*"></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <TextBlock Grid.Column="0" Text="{Binding Title}" />
    <TextBlock Grid.Column="1" Text="{Binding Answer}" />
</Grid>

<UserControl
x:Class="AppMvvm2.QuestionsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:AppMvvm2"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">

<UserControl.DataContext>
    <local:QuestionsViewModel></local:QuestionsViewModel>
</UserControl.DataContext>
<StackPanel Margin="0 50 0 0">
    <TextBlock Text="{Binding Description}"></TextBlock>
    <ItemsControl Name="Questions" Grid.Row="1" Grid.ColumnSpan="2" ItemsSource="{Binding questions}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <local:QuestionItemControl></local:QuestionItemControl>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</StackPanel>

<Page
x:Class="AppMvvm2.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:AppMvvm2"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">


<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <local:QuestionsControl></local:QuestionsControl>
</Grid>

+2

target, , : https://msdn.microsoft.com/en-us/windows/uwp/xaml-platform/custom-dependency-properties

, QuestionItemControl DataContext ItemsControl. DataContext QuestionItemControl ItemsControl:

<ItemsControl Name="Questions" Grid.Row="1" Grid.ColumnSpan="2" ItemsSource="{Binding Questions}">
    <ItemsControl.ItemTemplate>
        <DataTemplate x:DataType="model:Question">
            <uc:QuestionItemControl />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

... Title Answer QuestionItemControl.xaml:

<UserControl
x:Class="Question_Answer.View.Control.QuestionItemControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Question_Answer.View.Control"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
            <ColumnDefinition Width="*"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Column="0" Text="{Binding Title}" />
        <TextBlock Grid.Column="1" Text="{Binding Answer}" />
    </Grid>
</UserControl>

, DataContext QuestionItemControl Question ItemsSource ItemsControl.

+1

Finally, I will use the QuestionViewModel instead of the question. This probably implies synchronizing the collection of questions using the QuestionViewModel ...

0
source

Source: https://habr.com/ru/post/1667697/


All Articles