【问题标题】:Binding model-array to viewmodel in code-behind在代码隐藏中将模型数组绑定到视图模型
【发布时间】:2013-10-16 13:46:38
【问题描述】:

我遇到了一个问题,因为我有一个视图,其中所有控件都是在运行时创建的。

我正在尝试将它们中的每一个绑定到我的视图模型,但我认为我可能有错误的方法。

我们将以组合框为例。

我的模型包含数据:

public class ModelToContainTheData
{
    public string BuildType { get; set; }
    public string Section { get; set; }
    public string QuestionID { get; set; }
    public string Values { get; set; }
    public int Selectable { get; set; }
    public DateTime Changed { get; set; }
    public string User { get; set; }
}

然后我创建这个模型的数组,将下面的方法绑定到 ComboBox.SelectionChanged

private void ComboboxSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    var box = sender as ComboBox;

    foreach(ModelToContainTheDatamodel in currentSettingsModel)
    {
        if(model != null)
            if(model.QuestionID == box.Name)
            {
                model.Changed = DateTime.Now;
                model.Values = box.SelectedValue.ToString();
                model.User = "wc_set";
            }
    }
}

然后我想做的是将数组绑定到视图模型。有什么合适的方法可以做到这一点,还是我需要完全改变我的方法?

我认为 ObservableCollection 可能是要走的路,但我不知道如何绑定它。

【问题讨论】:

  • 您没有 Bind 视图模型的数据数组。您只需将其添加为 public 属性,然后将 Bind that 添加到 UI 中的控件。

标签: c# wpf arrays mvvm binding


【解决方案1】:

在您的示例中存在一些混淆。我建议您熟悉 MVVM 模式,然后再回到您的实际问题。 MVVM 的主要思想(我想您的目标是 MVVM,因为您在谈论模型、视图和 ViewModel)是解耦视图和模型。在 MVVM 中应避免订阅 UI 事件(如 SelectionChanged)。

您正在紧密耦合 UI 和模型,尤其是通过将模型属性与 UI 控件属性匹配 (model.QuestionID == box.Name)。

我将简要解释以 MVVM 方式解决您的问题的一般概念:

您的模型需要全面了解您的应用的域世界中正在发生的事情。你有问题,等等等等,所有这些都需要在领域逻辑中表示,也称为业务逻辑。你会有几节课。我只是根据我从您的代码中理解的内容来编造一些东西,不知道它是否符合您想要做的......

// Model for an answer ('Value' in your question
public class Answer { ... }

// Model for a question containing possible answers and the actual answer
public class Question 
{ 
   private Answer _answer;

   public List<Answer> PossibleAnswers { get; set; }

   public Answer Answer { get; set; }

   public DateTime Changed { get; set; }

   public Question()
   {
       // Acquire the values from wherever
       PossibleAnswers = ...;
   }
}

请注意,模型是完全独立的,这意味着它对 ViewModel 或 View 一无所知。

现在您为此模型创建一个 ViewModel,它将以一种视图可以绑定到您要显示的数据的方式公开属性。在最简单的情况下,您只需传递模型的属性。使用实现INotifyPropertyChanged 的适当基类。为此有很多 MVVM 框架,例如 MVVMLight:

public class QuestionViewModel : NotifyingObject
{
    public Question Model { get; private set; }

    public List<AnswerViewModel> PossibleAnswers 
    {
        get { return _possibleAnswers; }
    }

    public DateTime Changed 
    {
        get { return Model.Changed; }

    public AnswerViewModel Answer 
    {
        get { return _answer; }
        set 
        {
            _answer = value;
            // Set properties on your model which are effected
            _model.Answer = _answer.Model;
            _model.Changed = DateTime.Now;
            // Raise property changed events. They are needed
            // to update the UI
            RaisePropertyChanged("Answer");
            RaisePropertyChanged("Date");
        }
    }

    public QuestionViewModel(Question model)
    {
        Model = model;
        _possibleAnswers = Model.Answers.Select(a => new AnswerViewModel(a));
    }

}

public class AnswerViewModel { ... }

如您所见,ViewModel 了解模型并将其自身值的变化传递给模型。但同样,ViewModel 对 View 一无所知

View 使用 WPF 魔法绑定到 ViewModel。您只需要确保您的 View 的 DataContext 设置为 ViewModel。有很多方法可以实现这一点,像 MVVMLight 这样的 MVVM 框架也提供了实现这一点的方法。我这里只展示用法。假设你有 ComboBox:

<ComboBox ItemsSource="{Binding PossibleAnswers}" 
          SelectedItem="{Binding Answer}" />

就是这样。 WPF 负责其余的工作。

在更复杂的场景中,您的模型上有可以主动更改的集合,即不仅由用户在 UI 中进行更改,而且由于其他原因,它会变得更复杂一些。然后你需要同步 Model 和 ViewModel 上的集合。

这是你最终会遇到的更高级的东西。如果你到达那里,这个答案可能会对你有所帮助:

SO Answer on Collections on Model and ViewModels

这个答案一开始可能有点让人不知所措,所以我建议使用网络上许多非常好的资源之一来深入研究 MVVM。以我的回答为指导,为您的实际问题找到解决方案。如果您在 MVVM 教程和文档的帮助下理解了这个答案,那么您将能够以适当的 MVVM 方式解决您的问题。

编辑:关于 UI 元素的动态创建

您所描述的控件的动态创建是 WPF 和 MVVM 中一个非常自然的概念。基本思想是使用绑定到 ViewModelItems 集合的ItemsControl,并使用DataTemplates 指定每个 ViewModel 的呈现方式。没有限制,每个项目都可以在一个复杂的控件中呈现,并且可以通过 'ItemsControl's ItemsPanel 属性指定布局。在深入研究 MVVM 时,事情会变得很清楚,并且您的场景是使用 MVVM 解决的非常常见的事情。睁大眼睛看看 WPF 的 ItemsControl 以及你可以用它做什么......

【讨论】:

  • 非常感谢您的详尽回答。我对 MVVM 还是很陌生,但我的任务是修改现有程序。主要问题,正如我还进行了其他修改一样,这个视图的所有 GUI 组件都是动态创建的 - 对于每个 ComboBox,我必须将所有属性保存在我向您展示的模型中。因此,我认为简单地将 ComboBoxs 属性绑定到视图模型将太少,因为我需要一种方法来识别哪个组合框被更改,并且我不能传递组合框本身,因为这也会违反 MVVM。
  • @Ronni:当你对 MVVM 有了更深入的了解后,这些问题就会很容易解决。我会编辑我的答案,为你指明正确的方向,我相信你会管理的,一旦你有了这个概念。祝你的项目好运!
  • @Ronni:你去,有帮助吗?
  • 当然可以——我会尝试从这里开始,以前的开发人员通过创建实例并设置属性来添加控件,然后将其添加到 MainGridView.Children 列表中。我确信有可能找到解决方法,但我想正确地完成它以学习框架。再次感谢您抽出宝贵时间写出如此详细的答案!
  • 不客气!学习 MVVM 并不容易,但从开发人员的战略角度来看,你可以用它做什么,这绝对是值得的。玩得开心,如果您还有其他问题,请告诉我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-14
  • 1970-01-01
相关资源
最近更新 更多