【问题标题】:Adding controls to view from viewmodel添加控件以从视图模型查看
【发布时间】:2016-06-20 20:55:32
【问题描述】:

我正在尝试制作一个简单的任务管理器,作为在 WPF 应用程序中学习 prism 和 MVVM 的一种方式。

目前我有一个 MainWindow 和 MainWindowViewModel、一个 TaskList 和 TaskListViewModel,以及一个 Task 和 TaskViewModel。

当我加载应用程序时,我有 1 个按钮“新任务”最终目标是单击“新任务”按钮,然后让它在“任务列表”中添加一个新的“任务”,但是我不能似乎弄清楚如何从 MainWindowViewModel 添加控件。

主窗口视图模型:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using Prism.Mvvm;
using Prism.Commands;
using WpfApplication3.Views;

namespace WpfApplication3.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        public DelegateCommand NewTask { get; set; }

        public MainWindowViewModel()
        {
            NewTask = new DelegateCommand(Execute);
        }

        private void Execute()
        {
            MessageBox.Show("Worked");

        }
    }
}

主窗口 XAML:

<Window
        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:local="clr-namespace:WpfApplication3"
        xmlns:prism="http://prismlibrary.com/"
        xmlns:local1="clr-namespace:WpfApplication3.Views" x:Class="WpfApplication3.Views.MainWindow"
        prism:ViewModelLocator.AutoWireViewModel="True"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525" Loaded="Window_loaded">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="177*"/>
            <ColumnDefinition Width="340*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <StackPanel Orientation="Horizontal" Grid.ColumnSpan="2">
            <Button Grid.Row="0" x:Name="btnNew" Content="New Task" Command="{Binding NewTask}"/>
        </StackPanel>
        <StackPanel x:Name="taskList" Height="Auto" Grid.Row="1" VerticalAlignment="Top" Width="Auto"/>
        <local1:TaskList HorizontalAlignment="Left" VerticalAlignment="Top" Height="Auto" Grid.Row="1" Width="Auto"/>
    </Grid>
</Window>

任务列表 XAML:

<UserControl x:Class="WpfApplication3.Views.TaskList"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfApplication3.Views"
             mc:Ignorable="d" 
             d:DesignHeight="250" d:DesignWidth="177">
    <Grid>
        <StackPanel HorizontalAlignment="Left" Height="Auto" VerticalAlignment="Top" Width="Auto"/>
    </Grid>
</UserControl>

任务 XAML:

<UserControl x:Class="WpfApplication3.Views.Task"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfApplication3.Views"
             xmlns:prism="http://prismlibrary.com/"
             prism:ViewModelLocator.AutoWireViewModel="True"
             mc:Ignorable="d" 
             d:DesignHeight="50" d:DesignWidth="177">
    <Grid>
        <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="50" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="177"/>

    </Grid>
</UserControl>

问题:

如何动态添加“任务”用户控件到“任务列表”用户控件并保留 MVVM,而不在主窗口视图上添加代码隐藏?

我的直接想法是我需要通过 ViewModel,但我似乎无法让 MainWindowViewModel 看到视图对象(我也不确定它应该

【问题讨论】:

  • 希望大家可以看看列表框控件的ItemTemplate。您可以在哪里使用 UserControl 挂钩数据模板。
  • TaskList和Task View的作用是什么? DataEntry 的任务视图是否来自用户?
  • 好吧,我是 WPF 和 Prism 的新手,所以我可能只是不明白执行此操作的正确方法。 TaskList 控件的目的是保存“任务”控件,它将任务的详细信息加载到另一个部分。因此,当您单击任务时,它会加载任务的详细信息以供用户查看。
  • 我看到你是 wpf 的新手,但我喜欢你的想法。继续前进,你会摇滚;)

标签: c# wpf mvvm prism


【解决方案1】:

为您创建了一个小样本。看看吧。

<Window x:Class="ChkList_Learning.Window2"
    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"
    mc:Ignorable="d"
    Title="Window2" Height="300" Width="300">
<Grid>
    <StackPanel>
        <ListBox ItemsSource="{Binding TaskList}" x:Name="taskList">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding TaskId}"></TextBlock>
                        <TextBlock Text=" - "></TextBlock>
                        <TextBlock Text="{Binding TaskName}"></TextBlock>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="ID"></TextBlock>
            <TextBox Width="100" Text="{Binding ElementName=taskList,Path=SelectedItem.TaskId}"></TextBox>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="Song Name"></TextBlock>
            <TextBox Width="100"  Text="{Binding ElementName=taskList,Path=SelectedItem.TaskName}"></TextBox>
        </StackPanel>
    </StackPanel>
</Grid>

public partial class Window2 : Window
{
    public Window2()
    {
        InitializeComponent();
        this.DataContext = new TaskViewModel();
    }
}


class TaskViewModel
{
    public ObservableCollection<Task> TaskList { get; set; }

    public TaskViewModel()
    {
        TaskList = new ObservableCollection<Task>();
        for (int i = 0; i < 10; i++)
        {
            Task task = new Task();
            task.TaskId = (i + 1).ToString();
            task.TaskName = "Task Name" + (i + 1).ToString();
            TaskList.Add(task);
        }
    }
}

class Task
{
    public string TaskId { get; set; }
    public string TaskName { get; set; }

}

【讨论】:

  • 这里有两个cmets: 1. 您的命名约定可能会令人困惑,因为他在视图之后命名视图模型(MainWindow - MainWindowViewModel),这是推荐的。他有一个名为 Task 的视图 -> 你从中制作了一个模型。 2. 当您将所选项目数据绑定到列表框而不是 viewmodel 属性时,您的 taskviewmodel 的目的是什么?
【解决方案2】:

TaskList 和 TaskListViewModel 类在这里是绝对多余的。

只需创建属性

public ObservableCollection<TaskViewModel> Tasks {get;}

在 MainWindowViewModel 中

并将其数据绑定到 MainWindow.xaml 中的 ListBox 或 ItemsControl

当您向 Tasks 集合添加项目时,wpf 会自动为您将 ListBoxItem 添加到 ListBox 或 ItemsControl。现在,在 ListBox 中显示任务控件所需要做的就是设置 ItemTemplate

    <ListBox ItemsSource="{Binding TaskList}" x:Name="taskList">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <local:Task />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

【讨论】:

  • 抱歉回复晚了,但是如果我因为冗余而替换 taskList 视图,TaskList 绑定来自哪里(我同意,这感觉很奇怪。)
  • 因此,当我尝试向 Tasks 集合添加内容时,它现在表示 Tasks 集合为空。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-03
  • 1970-01-01
  • 1970-01-01
  • 2018-07-16
相关资源
最近更新 更多