DataContext 用于将 UserControl 与 DataTemplate 中的 ViewModel 绑定

发布于 2024-12-06 03:56:57 字数 1186 浏览 0 评论 0原文

我想要实现的是:

  • 将 ListView 绑定到 ItemRecords 的 ObservableCollection。
  • 拥有一个 TabControl,其中包含 ListView 中选择进行编辑的所有 ItemRecord 的详细视图。
  • 每个 TabItem 都包含一个 UserControl(“ItemInfo”),它使用 ItemInfoViewModel 作为其 VM(并且并非巧合的是 DataContext)。
  • ItemInfo UserControl 需要使用相应 ItemRecord 中的数据进行填充。

为了实现这一点,我尝试将 ItemRecord(在 ListView 中选择)传递给 ItemInfoViewModel。

最后,问题:在不破坏 MVVM 模式的情况下,您认为最好的方法是什么?

我看到的不太优雅的方式(实际上并不完全遵循 MVVM 原则)是在 UserControl 中定义 DependencyProperty ItemRecord,通过绑定提供其值,并在构造函数中(在 UserControl 的代码中)后面)将 ItemRecord 传递给 VM(我们通过转换 DataContext 获得)。

另一个问题是如何通过绑定实际传递 ItemRecord。 一旦我将 VM 设置为 UserControl 的 DataContext,我就不能仅使用 {Binding} 来指定 TabControl 源集合中的当前项目。 目前,我使用 ElementName 绑定到 TabControl 的 SelectedItem - 但这听起来不太健壮:-(

<localControls:TabControl.ContentTemplate>
    <DataTemplate>
        <ScrollViewer>
            <localControls:ItemInfo ItemRecord="{Binding ElementName=Tabs, Path=SelectedItem}"/>
        </ScrollViewer>
    </DataTemplate>
</localControls:TabControl.ContentTemplate>

任何好的建议将不胜感激!

Alex

What I'm trying to achieve is:

  • Have a ListView bound to an ObservableCollection of ItemRecords.
  • Have a TabControl that contains detailed view for all the ItemRecords in the ListView that were selected for editing.
  • Each TabItem contains a UserControl ("ItemInfo") that uses ItemInfoViewModel as its VM (and, not so coincidentally, DataContext).
  • ItemInfo UserControl needs to be populated with the data from the corresponding ItemRecord.

To achieve that, I'm trying to pass the ItemRecord (selected in the ListView) to ItemInfoViewModel.

Finally, the question: what do you think would be the best way to do this, without breaking the MVVM pattern?

The not-so-elegant way that I see (and it actually doesn't exactly follow the MVVM principles) is to have a DependencyProperty ItemRecord defined in the UserControl, provide its value via binding, and in the constructor (in the UserControl's code-behind) pass the ItemRecord to the VM (which we get by casting the DataContext).

The other problem is with how to actually pass the ItemRecord via binding.
Once I set the VM as the UserControl's DataContext, I cannot just use {Binding} to specify the current item in TabControl's source collection.
At the moment I am binding to the TabControl's SelectedItem using ElementName - but this doesn't sound too robust :-(

<localControls:TabControl.ContentTemplate>
    <DataTemplate>
        <ScrollViewer>
            <localControls:ItemInfo ItemRecord="{Binding ElementName=Tabs, Path=SelectedItem}"/>
        </ScrollViewer>
    </DataTemplate>
</localControls:TabControl.ContentTemplate>

Any good advice will be greatly appreciated!

Alex

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

农村范ル 2024-12-13 03:56:57

我认为你的问题是你不太理解 MVVM 模式;您仍然将其视为不同的控件相互通信。在 MVVM 中,它们不应该这样,每个控件都独立于所有其他控件与视图模型进行通信。视图模型控制(并提供)告诉控件如何行为的逻辑。

因此,理想情况下,您应该有类似的内容:

public ObservableCollection<ItemRecord> ListViewRecords 
{
   get { ... }
   set { ... }
}

public IEnumerable<ItemRecord> SelectedListViewRecords {
{
   get { ... }
   set { ... }
}

ListViewRecords 将绑定到 ListViewItemsSource 属性(实际属性可能会有所不同,具体取决于你正在使用的具体控件,我现在已经习惯了 Telerik 套件,所以这就是我的想法)。 SelectedListViewRecords 将绑定到 ListViewSelectedItems 属性。然后,对于 TabControl,您将拥有:

public ObservableCollection<MyTabItem> Tabs
{
   get { ... }
   set { ... }
}

public MyTabItem SelectedTab
{
   get { ... }
   set { ... }
}

同样,您将 Items 属性绑定到 Tabs,将 SelectedItem 绑定到 SelectedTabTabControl 上的 code>。现在您的视图模型包含所有逻辑,因此在您的 SelectedListViewRecords 中您可能会执行以下操作:

public IEnumerable<ItemRecord> SelectedListViewRecords {
{
   get { ... }
   set 
   {
       _selectedRecords = value;
       NotifyPropertyChanged("SelectedListViewRecords");

       Tabs.Clear(); // Clear the existing tabs
       // Create a new tab for each newly selected record
       foreach(ItemRecord record in value)
          Tabs.Add(new MyTabItem(record)); 
   }
}

因此这里的想法是控件除了发送和接收属性更改之外什么也不做,它们对底层数据、逻辑等。它们只是显示其绑定属性告诉它们要显示的内容。

I think your problem is you're not quite understanding the MVVM pattern here; you're still looking at this as the different controls talking to each other. Where in MVVM, they should not be, each control is communicating with the view model independently of all the others. And the view model controls (and supplies) the logic which tells the controls how to behave.

So, ideally you would have something like:

public ObservableCollection<ItemRecord> ListViewRecords 
{
   get { ... }
   set { ... }
}

public IEnumerable<ItemRecord> SelectedListViewRecords {
{
   get { ... }
   set { ... }
}

The ListViewRecords would be bound to the ItemsSource property of your ListView (the actual properties might vary based on the specific controls you're using, I'm used to the Telerik suite at the moment so that's where my head is). And the SelectedListViewRecords would be bound to the SelectedItems property of the ListView. Then for your TabControl you would have:

public ObservableCollection<MyTabItem> Tabs
{
   get { ... }
   set { ... }
}

public MyTabItem SelectedTab
{
   get { ... }
   set { ... }
}

Again, you would bind the Items property to the Tabs and SelectedItem to the SelectedTab on your TabControl. Now your view model contains all the logic, so in your SelectedListViewRecords you might do something like this:

public IEnumerable<ItemRecord> SelectedListViewRecords {
{
   get { ... }
   set 
   {
       _selectedRecords = value;
       NotifyPropertyChanged("SelectedListViewRecords");

       Tabs.Clear(); // Clear the existing tabs
       // Create a new tab for each newly selected record
       foreach(ItemRecord record in value)
          Tabs.Add(new MyTabItem(record)); 
   }
}

So the idea here is that the controls do nothing more than send and receive property changes, they know nothing of the underlying data, logic, etc. They simply show what their bound properties tell them to show.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文