MVVM DataBinding

时间:2013-01-22 20:44:56

标签: c# data-binding mvvm

我已经启动了一个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,但是正确绑定的最佳方式是什么?

感谢您的帮助,问候。

3 个答案:

答案 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}" ... /> )来显示加载的东西列表。因此,使用

将该控件绑定到ViewModel中的列表
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>

在这种情况下,如果用户编辑框中的文本,数据将在数据对象中更新,以便以后可以将其保存在数据库中。