我遇到了一个问题,因为我有一个 View ,其中所有控件都是在运行时创建的。
我正在尝试将它们中的每一个绑定(bind)到我的 View 模型,但我认为我可能采用了错误的方法。
我们将使用组合框作为示例。
我的模型包含数据:
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; }
}
然后我创建这个模型的数组,将以下方法绑定(bind)到 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";
}
}
}
然后我想做的是将数组绑定(bind)到 View 模型。有什么正确的方法可以做到这一点,还是我需要完全改变我的方法?
我认为 ObservableCollection 可能是可行的方法,但我不知道如何绑定(bind)它。
最佳答案
您的示例中有些困惑。我建议先熟悉 MVVM 模式,然后再回到您的实际问题。 MVVM 的主要思想(我想你的目标是 MVVM,因为你在谈论模型、 View 和 ViewModels)是解耦 View 和模型。在 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,它将以一种 View 可以绑定(bind)到您要显示的数据的方式公开属性。在最简单的情况下,您只需传递模型的属性。使用实现 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 魔法绑定(bind)到 ViewModel。您只需确保将 View 的 DataContext
设置为 ViewModel。有多种方法可以实现这一点,像 MVVMLight 这样的 MVVM 框架也提供了实现这一点的方法。我只会在这里展示用法。假设你有组合框:
<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 中一个很自然的概念。基本思想是使用绑定(bind)到 ViewModelItems 集合的 ItemsControl
,并使用 DataTemplate
指定每个 ViewModel 的呈现方式。没有限制,每个项目都可以在一个复杂的控件中呈现,并且可以通过“ItemsControl”的 ItemsPanel
属性指定布局。在深入研究 MVVM 时,事情会变得清晰,您的场景是使用 MVVM 解决的很常见的事情。请留意 WPF 的 ItemsControl
以及您可以用它做什么...
关于c# - 在代码隐藏中将模型数组绑定(bind)到 View 模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19267998/