WPF 数据绑定:视图未从视图模型更新

WPF databinding: view not updating from viewmodel

我的 WPF 应用程序以一种奇怪的方式工作 - 一些绑定有效,其他无效。

我有以下情况:

一个文本框 - 用户提供一个 ID。基于此 ID 加载或创建对象。其他一些属性由来自 loaded/new 对象的值更新。

ID 文本框的绑定工作正常。但是,其他两个视图(any other)不是。

我的代码示例: XAML:

<StackPanel Orientation="Horizontal" Margin="0,5,0,0">
            <TextBlock Text="ID" FontFamily="Segoe UI Light" />
            <TextBox x:Name="TB_PacientID" Width="100px" HorizontalAlignment="Left" Margin="5,0,0,0" Text="{Binding Path=PacientID}"/>
            <TextBlock x:Name="TBL_NovyPacient" Text="nový pacient" Margin="5,0,0,0" Foreground="Green" FontWeight="Bold" Visibility="{Binding Path=IsNewPacient,UpdateSourceTrigger=PropertyChanged,Converter={StaticResource BTVConverter}}"/>
        </StackPanel>
<WrapPanel x:Name="WP_PacientData" Margin="-2,5,2,5" Visibility="{Binding PacientLoaded,Converter={StaticResource BTVConverter}}">
 ...

视图模型:

public int? PacientID
{
    get
    {
        if (CurrentPacient == null)
            return null;
        return CurrentPacient.id;
    }
    set
    {
        if (value != null)
        {
            _pacient = App.instance.sessionData.serviceProxy.pacientById(value.Value);
            if (_pacient == null)
            {
                CurrentPacient = new Pacient() { id = value.Value };
                IsNewPacient = true;
            }
            else
            {
                CurrentPacient = _pacient;
            }                                                            
            OnPropertyChanged();
            PacientLoaded = true;
        }
    }
}

// ...

public bool IsNewPacient
{
    get{ return _isNewPacient; }
    set
    {
        _isNewPacient = value;
        OnPropertyChanged();
    }
}

//...

public bool PacientLoaded
{
    get{ return _pacientLoaded; }
    set
    {
        _pacientLoaded = value;
        OnPropertyChanged();
    }
}

想法: 用户输入 ID,加载或创建对象并显示 WrapPanel。如果对象是新创建的,那么也会显示 TextBlock。 转换器工作正常(在另一个 window 中测试)。

当 window 加载时,绑定建立良好(如果我在 ctor 中设置了一些假值)。在文本框中更改 ID 时,没有其他更新 - 除了 ID 本身 - setter 被很好地触发并且在调用 OnPropertyChanged 后读取新值。

我希望我遗漏了一些非常容易和愚蠢的东西。

-编辑: 当前状态: TB_PacientID 工作(更新),TBL_NovyPacient 和 WP_PacientData 不工作(更新)。 我想: 所有视图都从视图模型(代码属性)更新。

-编辑 2 我从头开始创建了一个非常简单的问题示例: A window - 两个文本框:

<Window x:Class="bindingTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <TextBox x:Name="TestTextBox" Text="{Binding ID, Mode=TwoWay}"/>
        <TextBox x:Name="SecondTextBox" Text="{Binding IsNew, Mode=TwoWay}"/>

    </StackPanel>
</Window>

代码隐藏:

 namespace bindingTest
 {
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new TestViewModel();
        }
    }
}

和视图模型class:

 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Linq;
 using System.Runtime.CompilerServices;
 using System.Text;
 using System.Threading.Tasks;
 namespace bindingTest
 {
    public abstract class ViewModelBase
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }        
    }

    public class TestViewModel : ViewModelBase
    {
        private bool _attOne;
        private int? id;        

        private bool _isNew;

        public bool IsNew
        {
            get
            {
                return _isNew;
            }
            set
            {
                _isNew = value;
                OnPropertyChanged();
            }
        }

        public int? ID
        {
            get
            {
                return id;
            }
            set
            {
                this.id = value;
                IsNew = true;
                OnPropertyChanged();
            }
        }
    }
}

我只是想要 - 如果我更改第一个文本框中的数字,我想在第二个文本框中自动显示 True。

我在您的代码示例中指出了三点:

  1. 您应该使用双向绑定来设置 ID。
  2. 您确定 _pacient = App.instance.sessionData.serviceProxy.pacientById(value.Value); 代码 returns 始终是相同的对象实例。
  3. 您是否正确使用了 INotifyPropertyChanged 界面?在大多数情况下,您引发了一个 属性 更改事件,如下所示:RaisePropertyChanged('PropertyName'); 您正在调用:'OnPropertyChanged();'

希望这对您有所帮助...

是的,我很笨

我的 ViewModel 基础 class 在从另一个项目合并时丢失了 INotifyPropertyChanged 接口。 所以我调用了 OnPropertyChanged,但它一直是我自己的 OnPropertyChanged 而不是 WPF 绑定等待的接口的实现。