添加到 ViewModel 中的 ObservableCollection 的元素未显示
Element added to ObservableCollection in ViewModel not displayed
WPF 世界的新手。这几天我的眼睛一直在受伤,正在寻找解决办法,但没能成功。
我想要实现的目标:
- 在视图模型中创建一个 ObservableCollection class
- 绑定 .xaml 文件中的数据
- 在 MainWindow.xaml.cs 中从 private void Button_Click 创建一个 "Add" 按钮(我稍后会创建命令 - 我只需要一步一步来并保持简单易懂的过程。)
看起来很简单,嗯?我设法在 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方法)?
- 还有其他更好的(但很简单!)方法吗?
我想这对你们来说是小菜一碟。谢谢!!
关于使用 2 个实例(一个在 xaml 中创建,另一个在代码隐藏中创建)是正确的。有 2 种方法可以解决这个问题。
使用在 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>
WPF 世界的新手。这几天我的眼睛一直在受伤,正在寻找解决办法,但没能成功。
我想要实现的目标:
- 在视图模型中创建一个 ObservableCollection class
- 绑定 .xaml 文件中的数据
- 在 MainWindow.xaml.cs 中从 private void Button_Click 创建一个 "Add" 按钮(我稍后会创建命令 - 我只需要一步一步来并保持简单易懂的过程。)
看起来很简单,嗯?我设法在 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方法)?
- 还有其他更好的(但很简单!)方法吗?
我想这对你们来说是小菜一碟。谢谢!!
关于使用 2 个实例(一个在 xaml 中创建,另一个在代码隐藏中创建)是正确的。有 2 种方法可以解决这个问题。
使用在 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>