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

我的用户控件有几个文本框,但正确绑定的最佳方法是什么?

感谢您的帮助,问候。

MVVM 数据绑定

编辑:将数据绑定到多个文本框

阅读您的评论后,我将详细说明我的文本框示例。

首先重要的是,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 中引入更多属性并相应地绑定它们。也许一个内部具有灵活数量的TextBoxListBox是一个解决方案,就像@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>

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