我已经启动了一个MVVM项目,现在我正在坚持使用正确的DataBinding。 我的项目有:
UserControl将ViewModel作为DataContext,如:
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();
}
}
最后是DataRepository代码:
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
});
}
}
我的UserControl有几个TextBox,但是正确绑定的最佳方式是什么?
感谢您的帮助,问候。
答案 0 :(得分:3)
编辑:将数据与多个文本框绑定
阅读完评论后,我将详细说明文本框的示例。
首先,ViewModel将对View中的内容进行建模,以便View在其所需的结构中获取所需的所有信息。这意味着,如果视图中有多个textboses,则ViewModel中需要多个字符串属性,每个文本框一个。
在您的XAML中,您可能会有类似
的内容<TextBox Text="{Binding ID, Mode=TwoWay}" />
<TextBox Text="{Binding SomeOtherData, Mode=TwoWay}" />
并在您的ViewModel中
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
方法来触发相应的事件。这告诉View该属性已更改,并且必须自行更新。
注意XAML中的Mode=TwoWay
。这意味着,价值变化的哪一方无关紧要,另一方将立即反映变化。因此,如果用户更改TwoWay
绑定TextBox
中的值,则相应的ViewModel属性将自动更改!反之亦然:如果以编程方式更改ViewModel属性,View将刷新。
如果要为多个数据项显示多个文本框,则必须在ViewModel中引入更多属性并相应地绑定它们。也许ListBox
内部有TextBox
个灵活的TestUserControl
是一个解决方案,就像@Haspemulator已经回答过一样。
将数据与集合控件绑定
在ListView
我想你有一个控件(比如<ListView ... ItemsSource="{Binding GetAllData}" ... />
)来显示加载的东西列表。因此,使用
AllData
首先,你必须明白绑定意味着不是“读取数据然后忘记ViewModel”。相反,只要View持续,就将View绑定到ViewModel(及其属性)。从这个角度来看,GetAllData
是一个比AllData
更好的名字(感谢@Malcolm O'Hare)。
现在,在您的代码中,每次View读取DataRepository
属性时,都会创建一个新的DataRepository
。由于Binding,这不是你想要的,而是你希望在View的整个生命周期中有一个AllData
实例,它用于读取初始数据,以后可以用来更新View ,如果底层数据库发生变化(可能是一个事件)。
要启用此类行为,您应该将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);
}
}
,以便View可以在发生更改时自动更新列表。
AddDataItem
现在,如果您稍后致电{{1}},ListView将自动更新。
答案 1 :(得分:2)
您的物业名称不好。你应该把它称为AllData,而不是GetAllData。
由于您要返回一个集合,您可能应该使用某种列表控件(ListBox,ListView)。
在那种情况下你会做
<ListBox ItemsSource="{Binding GetAllData}" />
答案 2 :(得分:0)
Guten Abend。 :)正如它已经提到的,因为你正在返回集合,所以最好使用ListBox。关于将ObservableCollection作为缓存的注释也绝对有效。我想补充一点,如果你需要编辑你的数据,你应该在ItemTemplate中使用TextBox:
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Text={Binding SomeOtherData,Mode=TwoWay} />
</DataTemplate>
</ListBox.ItemTemplate>
在这种情况下,如果用户编辑框中的文本,数据将在数据对象中更新,以便以后可以将其保存在数据库中。