MVVM 数据绑定
本文关键字:数据绑定 MVVM | 更新日期: 2023-09-27 17:55:22
我已经启动了一个MVVM项目,现在我卡在正确的数据绑定上。我的项目有:
将视图模型作为数据上下文的用户控件,如下所示:
public partial class TestUserControl: UserControl
{
public TestUserControl()
{
this.DataContext = new TestUserControlViewModel();
}
}
ViewModel 代码为 (BaseViewModel 类包含 PropertyChangedEventHandler):
public class TestUserControlViewModel : BaseViewModel
{
public KrankenkasseControlViewModel()
{}
public IEnumerable<DataItem> GetAllData
{
get
{
IGetTheData src= new DataRepository();
return src.GetData();
}
}
}
IGetTheData 是 DataContext 的接口:
public interface IGetTheData
{
IEnumerable<DataItem> GetData();
}
}
最后是数据存储库代码:
public class DataRepository : IGetTheData
{
private TestProjectDataContext dax = new TestProjectDataContext();
public IEnumerable<DataItem> GetData()
{
return (from d in this.dax.TestData
select new DataItem
{
ID = d.ID,
SomeOtherData = d.SomeOtherData
});
}
}
我的用户控件有几个文本框,但正确绑定的最佳方法是什么?
感谢您的帮助,问候。
编辑:将数据绑定到多个文本框
阅读您的评论后,我将详细说明我的文本框示例。
首先重要的是,ViewModel 将对视图中的事物进行建模,以便视图在所需的结构中获取所需的所有信息。这意味着,如果视图中有多个文本,则视图模型中需要多个字符串属性,每个文本框一个。
在你的 XAML 中,你可以有类似的东西
<TextBox Text="{Binding ID, Mode=TwoWay}" />
<TextBox Text="{Binding SomeOtherData, Mode=TwoWay}" />
并在您的视图模型中
public class TestUserControlViewModel : BaseViewModel {
private string id;
private string someOtherData;
public TestUserControlViewModel() {
DataItem firstItem = new DataRepository().GetData().First();
this.ID = firstItem.ID;
this.SomeOtherData = firstItem.SomeOtherData;
}
public string ID {
get {
return this.id;
}
set {
if (this.id == value) return;
this.id = value;
this.OnPropertyChangedEvent("ID");
}
}
public string SomeOtherData {
get {
return this.someOtherData;
}
set {
if (this.someOtherData == value) return;
this.someOtherData = value;
this.OnPropertyChangedEvent("SomeOtherData");
}
}
}
在这里,我假设在您的BaseViewModel
中有一种OnPropertyChangedEvent
方法来触发相应的事件。这会告知视图属性已更改,并且必须自行更新。
请注意 XAML 中的Mode=TwoWay
。这意味着,无论值在哪一边发生变化,另一侧都会立即反映变化。因此,如果用户更改了TwoWay
绑定TextBox
中的值,则相应的ViewModel属性将自动更改!反之亦然:如果以编程方式更改 ViewModel 属性,视图将刷新。
如果要为多个数据项显示多个文本框,则必须在 ViewModel 中引入更多属性并相应地绑定它们。也许一个内部具有灵活数量的TextBox
的ListBox
是一个解决方案,就像@Haspemulator已经回答的那样。
绑定到集合控件
在TestUserControl
中,我想你有一个控件(如ListView
)来显示加载的东西的列表。因此,将该控件与 ViewModel 中的列表绑定
<ListView ... ItemsSource="{Binding GetAllData}" ... />
首先,您必须了解绑定意味着不要"读取数据然后忘记视图模型"。相反,只要视图持续存在,您就可以将视图绑定到视图模型(及其属性)。从这个角度来看,AllData
是一个比GetAllData
好得多的名字(感谢奥黑尔@Malcolm)。
现在,在代码中,每次 View 读取 AllData
属性时,都会创建一个新DataRepository
。由于绑定,这不是您想要的,而是您希望在视图的整个生存期内有一个 DataRepository
实例,该实例用于读取初始数据,并在基础数据库发生更改(可能带有事件)时用于稍后更新视图。
若要启用此类行为,应将 AllData
属性的类型更改为 ObservableCollection
,以便视图可以在发生更改时自动更新列表。
public class TestUserControlViewModel : BaseViewModel
private ObservableCollection<DataItem> allData;
public TestUserControlViewModel() {
IGetTheData src = new DataRepository();
this.allData = new ObservableCollection<DataItem>(src.GetData());
}
public ObservableCollection<DataItem> AllData {
get {
return this.allData;
}
}
public void AddDataItem(DataItem item) {
this.allData.Add(item);
}
}
现在,如果您稍后调用AddDataItem
,列表视图将自动更新自身。
您的属性名称不正确。 你应该称它为AllData,而不是GetAllData。
由于您要返回集合,因此您可能应该使用某种列表控件(ListBox,ListView)。
在这种情况下,你会做的
<ListBox ItemsSource="{Binding GetAllData}" />
Guten Abend. :)如前所述,由于您要返回集合,因此最好使用 ListBox。关于将 ObservableCollection 作为缓存的评论也是绝对有效的。我想补充一点,如果您需要编辑数据,则应在ItemTemplate中使用TextBox:
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Text={Binding SomeOtherData,Mode=TwoWay} />
</DataTemplate>
</ListBox.ItemTemplate>
在这种情况下,如果用户编辑框中的文本,数据对象中的数据将更新,以便以后可以将其保存在数据库中。