未显示添加到ViewModel中ObservableCollection的元素

时间:2018-07-24 15:21:54

标签: c# wpf mvvm observablecollection

WPF领域中的新手。几天来,我一直在伤害我的眼睛,一直在寻找解决方案,但并没有做到正确。

我要实现的目标:

  • 在视图模型类中创建一个ObservableCollection
  • 绑定.xaml文件中的数据
  • 从MainWindow.xaml.cs 中的私有void Button_Click创建一个“添加”按钮(稍后我将创建命令-我只需要逐步进行操作,并使其易于理解即可。)

似乎很简单,嗯?我设法在MainWindow.xaml.cs中完成所有操作(仅使用ObservableCollection,还没有'PropertyChanged'),但是我无法使其在ViewModel中工作。

现在我的代码:

Client.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DataBindingTestInViewModel
{
    class Client
    {
        protected string _firstName;
        protected string _name;

        public string FirstName
        {
            get { return _firstName; }
            set { _firstName = value; }
        }

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
    }
}

MainWindow.xaml

<Window x:Class="DataBindingTestInViewModel.MainWindow"
        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:DataBindingTestInViewModel"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <Window.DataContext>
        <local:ViewModel />
    </Window.DataContext>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <ItemsControl Grid.Row="0" ItemsSource="{Binding Clients}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Label Grid.Column="0" Content="{Binding FirstName}" />
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

        <Button Grid.Row="1" Click="Button_Click">Add a client</Button>
    </Grid>
</Window>

MainWindow.xaml.cs (创建ViewModel + Button_Click事件的实例)

using System.Windows;

namespace DataBindingTestInViewModel
{
    /// <summary>
    /// Logique d'interaction pour MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        ViewModel viewmodel = new ViewModel();

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            viewmodel.AddClient();
        }
    }
}

ViewModel.cs

using System.Collections.ObjectModel;
using System.Windows;

namespace DataBindingTestInViewModel
{
    class ViewModel
    {
        private ObservableCollection<Client> _clients = new ObservableCollection<Client>();

        public ViewModel()
        {
            _clients.Add(new Client() { FirstName = "John", Name = "Doe" });
            _clients.Add(new Client() { FirstName = "Jane", Name = "Doe" });
            //MessageBox.Show("Constructeur du View Model appelé.");
        }
        public ObservableCollection<Client> Clients
        {
            get { return _clients; }
        }

        public void AddClient()
        {
            _clients.Add( new Client() { FirstName = "Donald", Name = "Trump" } );
            MessageBox.Show("First element : " + _clients[0].FirstName + "\n" +
                            "Third element : " + _clients[2].FirstName );

        }
    }
}

结果:

  • 显示“ John Doe / Jane Doe”
  • 当我单击按钮时,它不会在UI中添加内容。 (但是消息框工作正常。)

我认为会发生的事情:

MainWindow数据上下文已绑定到ViewModel的Client实例。我在MainWindow中的一个新实例中创建并添加元素-那不是datacontext中使用的那个。

问题:

  • 我是对的吗?如果是这样,如何解决(在MainWindow中调用Viewmodel实例的AddClient方法)?
  • 还有其他更好的方法(但请简单!)?

我想这对你们来说都是小菜一碟。谢谢!!

1 个答案:

答案 0 :(得分:1)

使用2个实例(一个是在xaml中创建的,另一个是在代码隐藏中的)是正确的。有两种方法可以解决这种情况。

使用在xaml中创建的实例。获取对该实例的引用,将DataContext转换为vm类型:

public partial class MainWindow : Window
{
    ViewModel viewmodel;

    public MainWindow()
    {
        InitializeComponent();
        viewModel = (ViewModel)DataContext;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        viewmodel.AddClient();
    }
}

使用在代码中创建的实例。也可以通过代码设置DataContext:

public partial class MainWindow : Window
{
    ViewModel viewmodel = new ViewModel();

    public MainWindow()
    {
        InitializeComponent();
        DataContext = viewmodel;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        viewmodel.AddClient();
    }
}

并删除xaml部分:

<Window.DataContext>
    <local:ViewModel />
</Window.DataContext>