3

我正在设计一个 WPF 用户控件,其中包含其他用户控件(想象一个 WidgetContainer,包含不同的小部件) - 使用 MV-VM 架构。在开发过程中,我在窗口中有 WidgetContainerView,窗口(视图)生成一个 WidgetContainerViewModel 作为其资源,在 WidgetContainerViewModel 的无参数构造函数中,我用一些示例小部件(WidgetViewModels)填充其暴露的集合。

WidgetContainer控件从window继承DataContext,里面有一个ListView,将Widgets绑定到WidgetView控件(在ListView.ItemTemplate里面)。

现在这在我的 WindowView 中工作正常,因为我看到了我的示例小部件,但是一旦我编辑 WidgetContainerView 或 WidgetView,就没有内容 - 在设计时,控件是独立的,它们不继承任何 DataContext,所以我没有看不到内容,并且在设计它们时遇到了麻烦(ListView 是空的,Widget 的字段也是如此......)。

我尝试将示例小部件添加到 WidgetView:

public partial class WidgetView : UserControl
{
    public WidgetView()
    {
        InitializeComponent();
        if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
        {
            //btw, MessageBox.Show(...) here sometimes crashes my Visual Studio (2008), but I have seen the message - this code gets executed at design time, but with some lag - I saw the message on reload of designer, but at that time, I have already commented it - wtf?
            this.DataContext = new WidgetViewModel(); //creates sample widget
        }
    }
}

但这不起作用——我仍然没有在设计师身上看到任何东西。

我还想在 WidgetView 中创建一个 WidgetViewModel 作为资源,如下所示:

<UserControl x:Class="MVVMTestWidgetsControl.View.WidgetView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    DataContext="WidgetViewModel" //this doesn't work!
    Height="Auto" Width="Auto">
    <UserControl.Resources>
        <ResourceDictionary>
            <ViewModel:WidgetViewModel x:Key="WidgetViewModel" />
        </ResourceDictionary>
    </UserControl.Resources>

    <TextBlock Text="{Binding Path=Title}"></TextBlock>

</UserControl>

但我不知道如何将 WidgetViewModel 分配为整个小部件的 DataContext - 我无法将 DataContext 属性添加到 UserControl,因为 WidgetViewModel 稍后在代码中定义。任何想法如何做到这一点?我可以以这种方式使用示例数据,并在代码中覆盖它,以便它在运行时具有正确的内容......

在开发用户控件时,您的最佳实践是什么?谢谢,设计空控件并不好玩:))。

4

2 回答 2

3

在您的第二个片段中,您应该能够将您的 DataContext 称为 DynamicResource:

DataContext="{DynamicResource WidgetViewModel}"

但是大多数自定义用户控件都有某种顶级布局容器,您可以将该容器上的 DataContext 设置为 StaticResource。

但是,在您的情况下,您可能需要考虑完全删除代码的 VM 部分,因为您正在编写自定义 UserControl。您应该问问自己,您从一个完全独立的 ViewModel 中获得了什么好处,而没有为一个 View 设计的真正的支持模型(即自定义 UserControl)。也许您可以定义一些 DependencyProperties 并使用它们?

于 2009-06-15T20:08:40.533 回答
1

我想出了几个解决方案:将 DC 添加为资源(它将使用无参数构造函数自动实例化),并在 View 的代码隐藏中执行以下操作:

    public PanelView()
    {
        InitializeComponent();

        if (!DesignerProperties.GetIsInDesignMode(new DependencyObject())) //DeleteAtRelease:
        {
            //we are in runtime, reset DC to have it inherited
            this.DataContextHolder.DataContext = DependencyProperty.UnsetValue;
        }

    }

更好的方法是仅在我们在设计时分配 DC,但 VS 不喜欢它 - 它仅在某些时候有效,而且非常不确定,甚至一旦崩溃。

设计时间的其他检查是:

        if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
        {
            this.DataContext = new WidgetViewModel();
        }
于 2009-06-16T22:35:04.823 回答