【问题标题】:Binding to an object property in ViewModel, or how to use multiple models with the same property names绑定到 ViewModel 中的对象属性,或者如何使用具有相同属性名称的多个模型
【发布时间】:2020-12-03 13:13:09
【问题描述】:

我正在尝试通过文本框中的 ViewModel 绑定到模型的属性。我在 ViewModel 中创建了一个包装器来访问模型的属性。每当我在此包装器的 get 部分中放置一个断点时,它都会触发,但在更改文本框内容后不会执行 set 部分中的断点。代码按照如下教程:https://www.codeproject.com/Articles/1193164/MVVM-Sample-application-with-a-focus-in-property

BaseViewModel 实现了 INPC 接口。我试图尽可能地遵循 MVVM “经验法则”。所以在这种情况下模型中没有INPC实现,视图只能绑定到VM。

我做错了什么?

XAML:

<TextBox Grid.Column="1" VerticalAlignment="Center" Text="{Binding Path=ProgramInfo.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

型号:

public class ProgramInfo 
    {
        private string _name;
        private string _description;
        
        public string Name
        {
            get => _name;
            set
            {
                _name = value;
            }
        }

        public string Description
        {
            get => _description;
            set
            {
                _description = value;
            }
        }
     
    }

视图模型:

class ProgramInfoViewModel : BaseViewModel
    {
        private ProgramInfo _programInfo;
        public ProgramInfo ProgramInfo
        {
            get => _programInfo;
            set
            {
                _programInfo = value;
                OnPropertyChanged("ProgramInfo");
            }
        }
    }

代码隐藏:

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new ProgramInfoViewModel();
        }
    }

【问题讨论】:

    标签: c# wpf xaml mvvm data-binding


    【解决方案1】:

    _programInfo 始终为空。你需要创建一个实例:

    class ProgramInfoViewModel : BaseViewModel
    {
        private ProgramInfo _programInfo = new ProgramInfo();
        public ProgramInfo ProgramInfo
        {
            get => _programInfo;
            set
            {
                _programInfo = value;
                OnPropertyChanged("ProgramInfo");
            }
        }
    }
    

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new ProgramInfoViewModel { ProgramInfo = new ProgramInfo() };
        }
    }
    

    模型属性的视图模型包装器如下所示:

    class ProgramInfoViewModel : BaseViewModel
    {
        private ProgramInfo _programInfo;
    
        private ProgramInfoViewModel(ProgramInfo programInfo)
        {
            _programInfo = programInfo;
        }
    
        public string ProgramInfoName
        {
            get => _programInfo.Name;
            set
            {
                _programInfo.Name = value;
                OnPropertyChanged("ProgramInfoName");
            }
        }
    }
    

    初始化:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var model = new ProgramInfo();
            DataContext = new ProgramInfoViewModel(model);
        }
    }
    

    绑定路径必须相应改变:

    <TextBox Text="{Binding Path=ProgramInfoName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
    

    【讨论】:

    • 感谢您的快速响应。当我在 GUI 中更改文本框值时,这仍然不会触发 set 命令中的断点。
    • 我在 ViewModel 的包装器中设置了断点。在具体的 OnPropertyChanged() 调用上。如果我在 Name {set } 中设置它,它将在我更改文本时触发。看起来视图是直接绑定到模型的 set 命令,而不是 get 命令?
    • ProgramInfo setter 不会被绑定触发。绑定源是 ProgramInfo 类中的 Name 属性。在 Name {set } 中放置断点进行检查。 ProgramInfo setter 可以通过赋值触发,像这样:`DataContext = new ProgramInfoViewModel { ProgramInfo = new ProgramInfo() };`
    • 这是有道理的。但这意味着视图可以直接编辑模型数据,这不是根据 MVVM 对吗?我该如何解决这个问题?
    • 您的编辑工作就像一个魅力。我决定在 VM 中创建 ProgramInfo 实例,以防止在代码隐藏中引用模型。像我试图做的那样嵌套属性本来是一个很棒的功能,但我猜这正是 Fody.Weaves 发挥作用的地方。非常感谢:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-19
    • 2020-03-25
    • 2016-07-19
    • 2017-02-28
    • 2016-01-04
    • 2015-04-09
    相关资源
    最近更新 更多