【问题标题】:Element added to ObservableCollection in ViewModel not displayed添加到 ViewModel 中的 ObservableCollection 的元素未显示
【发布时间】:2019-01-01 07:05:16
【问题描述】:

在 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 中添加东西。 (但 Messagebox 工作正常。)

我认为会发生什么:

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

问题:

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

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

【问题讨论】:

    标签: c# wpf mvvm observablecollection


    【解决方案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>
    

    【讨论】:

    • 第一次在 Stack Overflow 上,非常开心!非常非常感谢(我快哭了)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-16
    • 1970-01-01
    • 1970-01-01
    • 2015-04-07
    相关资源
    最近更新 更多