【问题标题】:Dynamically Notify the View from the View-Model in WPF从 WPF 中的 View-Model 动态通知视图
【发布时间】:2026-01-20 00:05:01
【问题描述】:

在我的 WPF 应用程序中,我必须创建一个对象设计器。此设计器是许多其他用户控件的 ListView(自定义网格,其中包含 costum-stackpanel,其中包含...,其中包含我要显示的自定义对象)。

因此,为了更好地构建我的设计器,我为每个层次结构创建了一个模板,并将其放入视图中(作为用户控件)。同时,我为这些视图中的每一个创建了相应的视图模型。

为了将视图绑定到他们的视图模型,我在文件 App.xaml 中放入了以下代码:

<Application.Resources>
    <DataTemplate DataType="{x:Type ViewModel:DesignerViewModel}">
        <View:Designer />
    </DataTemplate>
    <DataTemplate DataType="{x:Type ViewModel:FirstLevelViewModel}">
        <View:FirstLevel />
    </DataTemplate>
    <DataTemplate DataType="{x:Type ViewModel:SecondLevelViewModel}">
        <View:Secondlevel />
    </DataTemplate>
    <DataTemplate DataType="{x:Type ViewModel:ThirdLevelViewModel}">
        <View:Thirdlevel />
    </DataTemplate>
    <DataTemplate DataType="{x:Type ViewModel:CircleViewModel}">
        <View:Circle />
    </DataTemplate>
    <DataTemplate DataType="{x:Type ViewModel:RectangleViewModel}">
        <View:Rectangle />
    </DataTemplate>
</Application.Resources>

它在我第一次加载应用程序时起作用(我认为是因为绑定仅在创建视图的构造函数时完成)。但是在那之后,View-Models 中的每一次修改都不会自动通知给视图!!!

我找到的唯一解决方案是在任何视图模型修改后重新创建我的设计器视图!

有人有更好的解决方案吗?因为我认为我的解决方案不是很干净!

注意:我在所有 viewModel 中实现了 INotifyPropertyChanged。

更新>>>>

那么,我举个例子:

这是我的 Designer Xaml:

<Grid>
    <ListView SelectionMode="Single"
    VerticalAlignment="Stretch" HorizontalAlignment="Stretch" 
    ItemsSource="{Binding FirstLevelViewModelList}" >

        <ListView.ItemTemplate>
            <DataTemplate>
              <View:FirstLevel HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"/>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

</Grid>

这是我的 DesignerViewModel 类:

 public class DesignerViewModel : AViewModel
{
    #region Property

    public int FirstLevelCounter
    {
        get;
        set;
    }

    private List<FirstLevelViewModel> FirstLevelViewModelList;

    public List<FirstLevelViewModel> FirstLevelViewModelList
    {
        get { return FirstLevelViewModelList; }
        set { FirstLevelViewModelList = value; 
OnPropertyChanged("FirstLevelViewModelList"); }
    }

    #region Constructor

    /// <summary>
    /// Constructor
    /// </summary>
    private DesignerViewModel()
    {
        FirstLevelViewModelList = new List<FirstLevelViewModel>();
        FirstLevelCounter = 0;

    }

    private static DesignerViewModel instance = null;
    private static readonly object padlock = new object();

    public static DesignerStringViewModel Instance
    {
        get
        {
            lock (padlock)
            {
                if (instance == null)
                {
                    instance = new DesignerViewModel();
                }
                return instance;
            }
        }
    }
 }

这是我的 FirstLevel Xaml:

<Grid>
    <ListView SelectionMode="Single"
    VerticalAlignment="Stretch" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"
    ScrollViewer.VerticalScrollBarVisibility="Auto" ItemsSource="{Binding SecondLevelViewModelList}" BorderBrush="Transparent" Background="Transparent" Height="auto">
    </ListView>
</Grid>

最后,这是我的 FirstLevelViewModel 类:

公共类 FirstLevelViewModel : AViewModel { #region 属性

    private List<SecondLevelViewModel> SecondLevelViewModelList;
    public List<SecondLevelViewModel> SecondLevelViewModelList
    {
        get { return SecondLevelViewModelList; }
        set { SecondLevelViewModelList = value; 
OnPropertyChanged("SecondLevelViewModelList"); }
    }


    #region Constructor


    public FirstLevelViewModel()
    {
        SecondLevelViewModelList = new List<SecondLevelViewModel>();

    }

    #endregion 

}

更新结束>>>>>

【问题讨论】:

    标签: wpf xaml data-binding mvvm user-controls


    【解决方案1】:

    普通列表不实现INotifyCollectionChanged,这是必要的,类似于 INotifyPropertyChanged 告诉 WPF 和绑定引擎发生了一些变化,因此视图可以更新。

    你有两个选择:

    1. 使用ObservableCollection 代替列表
    2. 创建自己的集合类型并实现 INotifyCollectionChanged

    【讨论】:

      【解决方案2】:

      您的视图模型需要实现INotifyPropertyChanged 并在其属性发生更改时引发PropertyChanged 事件。

      【讨论】:

      • 我当然做到了!但我认为问题在于将绑定放入 App.Xaml !所以在完成创建之后......绑定丢失了!
      • @Alvaro:不,这不是正在发生的事情。也许您需要提供有关您的代码的更多信息。