【问题标题】:How to setup UserControl如何设置用户控件
【发布时间】:2014-03-07 11:53:11
【问题描述】:

在应用程序中,我有(简化的)任务:

该应用程序管理有关人员的信息。这些人存储在某个地方(没关系)。 用户可以在列表中添加和删除人员。

人员列表(在程序中经常使用)如下所示:

<UserControl>
...
    <StackPanel>
        <ListBox 
            ItemsSource="{Binding Persons}" 
            SelectedItem="{Binding SelectedPerson}"
            SelectionMode="Single"/>

        <StackPanel Orientation="Horizontal">
            <Button Content="Add Person" Command="{Binding AddPersonCommand}" />
            <Button Content="Remove Person" Command="{Binding RemovePersonCommand}" />
        </StackPanel>
    </StackPanel>
...
</UserControl>

在它的背后是一个我想用于实现的 ViewModel。

现在我希望将这个控件嵌入到另一个控件/窗口中,如下所示:

<personcontrol:PersonControl PersonsCollectionDP="{Binding PersonsFromMainVM}" SelectedPersonDP="{Binding SelectedPersonFromMainVM}" />

(PersonsVMSelectedPersonVM 是嵌入 PersonControl-UC、PersonsDP 的 UC/Window 的 VM 中的属性SelectedPersonDP 是 PersonControl-UC 的 DependencyProperty。)

我的问题是将 UC 的属性作为 DependencyProperty 并且(同时)在 UC-ViewModel 中作为属性。

我怎样才能做到这一点?


更新 1

找到this link 正是在此讨论了我的问题但仍未得到解答。也许有人有一个新想法......

【问题讨论】:

    标签: wpf mvvm dependency-properties


    【解决方案1】:

    这都是关于数据上下文的。您可以将绑定保留在用户控件定义中,稍后在您将 UC 绑定数据上下文嵌入到相应 VM 的部分中,该 VM 提供您的人员数据源。

    <Window>
        <personcontrol:PersonControl DataContext="{Binding PersonsVM}" />
    </Window>
    

    在虚拟机中你会拥有

    public class WindowVM 
    {
       public PersonsUCProviderVM PersonsVM {get;set;}
    }
    
    public class PersonsVM
    {
       public List<Person> Persons {get;set;}
       public Person SelectedPerson {get;set;}
       public ICommand AddPersonCommand {get;set;}
       public ICommand RemovePersonCommand {get;set;}
    }
    

    【讨论】:

    • 好的,所以你想在MainWindow-VM中保存一个UC-VM......但是如果UC和MainWindow(以及相应的VM)是由不同的人实现的呢? MainWindowVM 程序员不应该看到 UC-VM 的详细信息。他只是想像其他所有 UC 一样使用它,并将他的 VM-Properties 绑定到 UC 的 DP
    • 如果你想让它成为一个可重用的控件,那么你应该通过依赖属性来操作。为该 UC 创建一个 VM(就像您可能所做的那样)。当 DP 更改时连接事件并根据它们更新本地 VM。当本地 VM 的选定人员更改时,也要更改依赖属性。只需确保您的 VM 知道控制(但这是 MVVM 模式的突破)。可重用控件不应使用 VM。只是简单的代码隐藏,因为根本不需要虚拟机。
    • 可重用控件不应使用虚拟机。只是简单的代码隐藏,因为根本不需要虚拟机。 -- 我很难相信......你对此有什么论据吗?真正复杂的 UC 呢?
    • 在我看来 UC 是轻量级的可重用组件。如果您有使用 VM 的 UC 或复杂 UC,则它已经是 View 而不是 UC。因此,视图应遵循自己域的准则。此外,在大多数情况下,UC 没有自己的数据集。他们使用绑定或符号定义的数据源,如 ListBox。甚至 TreeView 也被称为 View,因为它不仅仅是一个 UC——它用额外的数据和特性包装了绑定集合。最后,UC 的数据绑定和虚拟机只是恕我直言的开销。
    【解决方案2】:

    编辑:

    通常在使用 usercontrol 和 DP 时使用 elementname 绑定。(永远不要将 DataContext 设置为 self)

    <personcontrol:PersonControl PersonsCollectionDP="{Binding PersonsFromMainVM}" SelectedPersonDP="{Binding SelectedPersonFromMainVM}" />
    

    那么你的用户控件应该是这样的

    <UserControl x:Name="uc">
    <StackPanel>
        <ListBox 
            ItemsSource="{Binding ElementName=uc, Path=PersonsCollectionDP}" 
            SelectedItem="{Binding ElementName=uc, Path=SelectedPersonDP}"
            SelectionMode="Single"/>
    </StackPanel>
    </UserControl>
    

    【讨论】:

    • 那么这意味着您会将我的 ViewModel 公开为 DP?我用&lt;personcontrol:PersonControl PersonsDP.Persons="{Binding PersonsFromMainVM}"/&gt; 试了一下,但编译失败:“XML 命名空间中不存在 PersonsDP.Persons 属性 ...”
    • 我只是更改了用户控件 xaml,您的主窗口 xaml 是“好的”。我想说的是,您绑定的依赖属性是在用户控件中使用 elementname 绑定(或 relativesource 绑定)定义的。我只是猜测您的 PersonsDP DP 是 PersonVM 的类型,因为您绑定到它。 。在您的 USERCONTROL 中,您绑定到您的 USERCONTROL DP!
    • 我知道我误导了你......我编辑了我的帖子以澄清:PersonsDP 是一个 DP,但不是 PersonVM 类型。我只想将 Persons-Collection 公开为 DP...那么如何从 MainWindow-xaml 绑定到 DP??
    • 您必须将 PROPERTIES 而不是 DP 从您的 mainwindowVIEWMODEL 绑定到您的 UserControl 的 DP
    猜你喜欢
    • 2017-01-21
    • 1970-01-01
    • 1970-01-01
    • 2012-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多