繁体   English   中英

将模型数组绑定到代码隐藏中的viewmodel

[英]Binding model-array to viewmodel in code-behind

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

我试图将它们中的每一个绑定到我的viewmodel,但我想我可能有错误的方法。

我们将使用组合框作为示例。

我的模型包含数据:

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";
            }
    }
}

我想要做的是将数组绑定到viewmodel。 有没有正确的方法来做到这一点,还是我需要完全改变我的approch?

我认为一个ObservableCollection可能是要走的路,但我无法弄清楚我是如何绑定它的。

你的例子中有一些混乱。 我建议熟悉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 了解 Model并将其自身值的更改转发给模型。 但同样, ViewModel并没有关于View的任何信息

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

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

而已。 WPF负责其余的工作。

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

VMCollection同步

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

回答模型和ViewModel上的集合

这个答案起初可能有点压倒性,所以我建议使用网络上众多非常好的资源之一挖掘MVVM。 使用我的答案作为指导,为您的实际问题找到解决方案。 如果您在MVVM教程的帮助下理解了这个答案,那么您将适合以适当的MVVM方式解决您的问题。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM