首页 > 解决方案 > 添加到 ViewModel 中的 ObservableCollection 的元素未显示

问题描述

WPF 世界中的新手。我这几天一直在伤害我的眼睛,寻找解决方案,但没有设法解决。

我想要达到的目标:

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

现在我的代码:  

客户端.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; }
        }
    }
}

主窗口.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();
        }
    }
}

视图模型.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 );

        }
    }
}

结果 :

我认为会发生什么:

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

问题 :

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

标签: c#wpfmvvmobservablecollection

解决方案


您使用 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>

推荐阅读