【问题标题】:Adding initialized ViewModels to ObservableCollection displaying null property values将初始化的 ViewModel 添加到 ObservableCollection,显示空属性值
【发布时间】:2020-10-30 05:14:08
【问题描述】:

将 ViewModel 添加到 ObservableCollection 时,它在 MainWindow 上显示为 ItemsControl,而 ObservableCollection 作为 ItemsSource。 View 的初始值显示为 null。我知道这一点,因为在调试和更改 TextBox 的值时,我看到 Name 字段设置为 null,但是当我按下按钮添加新的 ViewModels 时,它正在设置 Name 字段但不显示名称。这个应用程序已经被压缩以方便调试。因此,当 ObservableCollection 与视图通信时,它似乎没有以某种方式接收到正确的值。

主窗口

<Window x:Class="LifeCalculator.Views.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:prism="http://prismlibrary.com/"
    prism:ViewModelLocator.AutoWireViewModel="True"
    xmlns:myControl="clr-namespace:LifeCalculator.Views" xmlns:views="clr-namespace:LifeFinanceCalculator.Views"
    Title="{Binding Title}" Height="350" Width="525">
<Grid>
    <Button Margin="47,24,373,269" Content="Add ViewModels" Command="{Binding AddCommandItem}"/>
    <ScrollViewer Margin="28,75,37,72">
        <ItemsControl ItemsSource="{Binding ListExampleItems}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <views:exampleView/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </ScrollViewer>
</Grid>

MainWindowViewModel

using Prism.Mvvm;
using System.Collections.ObjectModel;
using LifeFinanceCalculator.ViewModels;
using System.Windows.Input;
using Prism.Commands;

namespace LifeCalculator.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        private ObservableCollection<exampleViewModel> _listExampleItems;
        public ObservableCollection<exampleViewModel> ListExampleItems 
        {
            get => _listExampleItems;
            set
            {
                SetProperty(ref _listExampleItems, value);
            }
        }
        public ICommand AddCommandItem { get; set; }

        public MainWindowViewModel()
        {
            _listExampleItems = new ObservableCollection<exampleViewModel>();
            AddCommandItem = new DelegateCommand(ListItem);
        }

        private void ListItem()
        {
            _listExampleItems.Add(new exampleViewModel() { Name = "Chris" });
            _listExampleItems.Add(new exampleViewModel() { Name = "Olivia" });
        }
    }
}

示例视图

<UserControl x:Class="LifeFinanceCalculator.Views.exampleView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:prism="http://prismlibrary.com/"
             prism:ViewModelLocator.AutoWireViewModel="True">
    <Grid>
        <TextBox Text="{Binding Name}" FontSize="22"/>
    </Grid>
</UserControl>

exampleViewModel

using Prism.Mvvm;

namespace LifeFinanceCalculator.ViewModels
{
    public class exampleViewModel : BindableBase
    {
        private string _name;
        public string Name
        {
            get => _name;
            set
            {
                SetProperty(ref _name, value);
            }
        }
        public exampleViewModel()
        {
        }
    }
}

【问题讨论】:

  • 我想我知道你在做什么,我假设 Prism ViewModelLocator 可能正在重新初始化数据上下文......因此我当然有空值......听起来对吗?
  • 哦棱镜!基本上是的。这是由于多个虚拟机而导致孤立虚拟机的情况。当有人在 XAML 中设置 DataContext 并错误地隐藏代码时,直接 WPF(比如没有 Prism,没有 DI)也可能发生这种情况。在那里做过;)

标签: c# wpf prism


【解决方案1】:

Prism 使用的ViewModelLocator 是问题所在。 ViewModelLocator 使用新的 ViewModel 重新初始化 View。解决问题:

prism:ViewModelLocator.AutoWireViewModel = "False"

【讨论】:

  • 实际上,对于 Prism 8,几乎所有视图模型都必须这样做,因为 AutoWire=True 是新的默认值。
猜你喜欢
  • 2019-01-01
  • 2021-06-11
  • 1970-01-01
  • 1970-01-01
  • 2020-08-06
  • 1970-01-01
  • 2021-01-09
  • 1970-01-01
  • 2021-12-17
相关资源
最近更新 更多